From 0f9b21f1fba0a78e81e03eeab30ebe10f48e56fa Mon Sep 17 00:00:00 2001 From: skydoves Date: Sun, 1 Oct 2023 17:59:42 +0900 Subject: [PATCH 1/2] Bump AGP, Compose, Kotlin, and other androidx dependencies --- .editorconfig | 2 +- app/build.gradle | 81 +++++++++--------- app/src/main/AndroidManifest.xml | 34 ++++---- .../colorpicker/compose/Configuration.kt | 4 +- .../colorpicker/compose/Dependencies.kt | 12 +-- colorpicker-compose/build.gradle | 79 ++++++++--------- gradle/wrapper/gradle-wrapper.jar | Bin 61574 -> 61608 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 4 +- 9 files changed, 110 insertions(+), 108 deletions(-) diff --git a/.editorconfig b/.editorconfig index d1999ac..376f7bb 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,5 +1,5 @@ root = true [*] # Most of the standard properties are supported -indent_size=4 +indent_size=2 max_line_length=100 \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index a145d9e..12d904e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -3,62 +3,63 @@ import com.github.skydoves.colorpicker.compose.Dependencies import com.github.skydoves.colorpicker.compose.Versions plugins { - id 'com.android.application' - id 'org.jetbrains.kotlin.android' + id 'com.android.application' + id 'org.jetbrains.kotlin.android' } android { - compileSdkVersion Configuration.compileSdk - defaultConfig { - applicationId "com.github.skydoves.colorpickercomposedemo" - minSdkVersion Configuration.minSdk - targetSdkVersion Configuration.targetSdk - versionCode Configuration.versionCode - versionName Configuration.versionName - } + compileSdk Configuration.compileSdk + namespace "com.github.skydoves.colorpickercomposedemo" + defaultConfig { + applicationId "com.github.skydoves.colorpickercomposedemo" + minSdkVersion Configuration.minSdk + targetSdkVersion Configuration.targetSdk + versionCode Configuration.versionCode + versionName Configuration.versionName + } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } - kotlinOptions { - jvmTarget = '1.8' - } + kotlinOptions { + jvmTarget = '1.8' + } - composeOptions { - kotlinCompilerExtensionVersion Versions.COMPOSE_COMPILER - } + composeOptions { + kotlinCompilerExtensionVersion Versions.COMPOSE_COMPILER + } - buildFeatures { - compose true - } + buildFeatures { + compose true + } - packagingOptions { - resources { - excludes += '/META-INF/{AL2.0,LGPL2.1}' - } + packagingOptions { + resources { + excludes += '/META-INF/{AL2.0,LGPL2.1}' } + } - lintOptions { - abortOnError false - } + lintOptions { + abortOnError false + } } dependencies { - implementation project(":colorpicker-compose") + implementation project(":colorpicker-compose") - implementation Dependencies.material + implementation Dependencies.material - implementation platform(Dependencies.composeBom) - implementation Dependencies.composeUI - implementation Dependencies.composeMaterial - implementation Dependencies.composeRuntime - implementation Dependencies.composeTooling - implementation Dependencies.composeActivity - implementation Dependencies.composeNavigation + implementation platform(Dependencies.composeBom) + implementation Dependencies.composeUI + implementation Dependencies.composeMaterial + implementation Dependencies.composeRuntime + implementation Dependencies.composeTooling + implementation Dependencies.composeActivity + implementation Dependencies.composeNavigation - implementation Dependencies.photoPicker + implementation Dependencies.photoPicker } apply from: "$rootDir/spotless.gradle" \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c5b2a0d..64a614f 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,23 +1,23 @@ + package="com.github.skydoves.colorpickercomposedemo"> - - - - + + + + - - - - + + + + \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/com/github/skydoves/colorpicker/compose/Configuration.kt b/buildSrc/src/main/kotlin/com/github/skydoves/colorpicker/compose/Configuration.kt index 9efb18c..c34b8a6 100644 --- a/buildSrc/src/main/kotlin/com/github/skydoves/colorpicker/compose/Configuration.kt +++ b/buildSrc/src/main/kotlin/com/github/skydoves/colorpicker/compose/Configuration.kt @@ -1,8 +1,8 @@ package com.github.skydoves.colorpicker.compose object Configuration { - const val compileSdk = 33 - const val targetSdk = 33 + const val compileSdk = 34 + const val targetSdk = 34 const val minSdk = 21 const val majorVersion = 1 const val minorVersion = 0 diff --git a/buildSrc/src/main/kotlin/com/github/skydoves/colorpicker/compose/Dependencies.kt b/buildSrc/src/main/kotlin/com/github/skydoves/colorpicker/compose/Dependencies.kt index ba852c4..ddefd1e 100644 --- a/buildSrc/src/main/kotlin/com/github/skydoves/colorpicker/compose/Dependencies.kt +++ b/buildSrc/src/main/kotlin/com/github/skydoves/colorpicker/compose/Dependencies.kt @@ -1,19 +1,19 @@ package com.github.skydoves.colorpicker.compose object Versions { - internal const val ANDROID_GRADLE_PLUGIN = "7.4.2" - internal const val ANDROID_GRADLE_SPOTLESS = "6.19.0" + internal const val ANDROID_GRADLE_PLUGIN = "8.1.1" + internal const val ANDROID_GRADLE_SPOTLESS = "6.21.0" internal const val GRADLE_NEXUS_PUBLISH_PLUGIN = "1.3.0" - internal const val KOTLIN = "1.8.22" - internal const val KOTLIN_GRADLE_DOKKA = "1.8.20" + internal const val KOTLIN = "1.9.10" + internal const val KOTLIN_GRADLE_DOKKA = "1.9.0" internal const val KOTLIN_BINARY_VALIDATOR = "0.13.1" internal const val KOTLIN_COROUTINE = "1.7.2" internal const val MATERIAL = "1.6.0" internal const val ANDROIDX_CORE_KTX = "1.8.0" - internal const val COMPOSE_BOM = "2023.06.01" - internal const val COMPOSE_COMPILER = "1.4.8" + internal const val COMPOSE_BOM = "2023.09.01" + internal const val COMPOSE_COMPILER = "1.5.3" internal const val COMPOSE_ACTIVITY = "1.7.2" internal const val COMPOSE_NAVIGATION = "2.6.0" internal const val PHOTO_PICKER = "1.0.0-alpha06" diff --git a/colorpicker-compose/build.gradle b/colorpicker-compose/build.gradle index f589b4d..10732d1 100644 --- a/colorpicker-compose/build.gradle +++ b/colorpicker-compose/build.gradle @@ -3,65 +3,66 @@ import com.github.skydoves.colorpicker.compose.Dependencies import com.github.skydoves.colorpicker.compose.Versions plugins { - id 'com.android.library' - id 'org.jetbrains.kotlin.android' - id 'org.jetbrains.dokka' - id 'binary-compatibility-validator' + id 'com.android.library' + id 'org.jetbrains.kotlin.android' + id 'org.jetbrains.dokka' + id 'binary-compatibility-validator' } ext { - PUBLISH_GROUP_ID = Configuration.artifactGroup - PUBLISH_ARTIFACT_ID = 'colorpicker-compose' - PUBLISH_VERSION = rootVersionName + PUBLISH_GROUP_ID = Configuration.artifactGroup + PUBLISH_ARTIFACT_ID = 'colorpicker-compose' + PUBLISH_VERSION = rootVersionName } apply from: "${rootDir}/scripts/publish-module.gradle" android { - compileSdkVersion Configuration.compileSdk - defaultConfig { - minSdkVersion Configuration.minSdk - targetSdkVersion Configuration.targetSdk - } + compileSdk Configuration.compileSdk + namespace "com.github.skydoves.colorpicker.compose" + defaultConfig { + minSdkVersion Configuration.minSdk + targetSdkVersion Configuration.targetSdk + } - buildFeatures { - compose true - buildConfig false - } + buildFeatures { + compose true + buildConfig false + } - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } - composeOptions { - kotlinCompilerExtensionVersion Versions.COMPOSE_COMPILER - } + composeOptions { + kotlinCompilerExtensionVersion Versions.COMPOSE_COMPILER + } - kotlinOptions { - jvmTarget = '1.8' - } + kotlinOptions { + jvmTarget = '1.8' + } - lintOptions { - abortOnError false - } + lintOptions { + abortOnError false + } } tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all { - kotlinOptions.freeCompilerArgs += [ - "-Xexplicit-api=strict", - "-Xopt-in=androidx.compose.ui.ExperimentalComposeUiApi" - ] + kotlinOptions.freeCompilerArgs += [ + "-Xexplicit-api=strict", + "-Xopt-in=androidx.compose.ui.ExperimentalComposeUiApi" + ] } dependencies { - implementation Dependencies.androidxCoreKtx + implementation Dependencies.androidxCoreKtx - implementation platform(Dependencies.composeBom) - implementation Dependencies.composeUI - implementation Dependencies.composeRuntime - implementation Dependencies.composeFoundation - implementation Dependencies.composeTooling + implementation platform(Dependencies.composeBom) + implementation Dependencies.composeUI + implementation Dependencies.composeRuntime + implementation Dependencies.composeFoundation + implementation Dependencies.composeTooling } apply from: "$rootDir/spotless.gradle" \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 943f0cbfa754578e88a3dae77fce6e3dea56edbf..ccebba7710deaf9f98673a68957ea02138b60d0a 100644 GIT binary patch delta 5094 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 delta 5107 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 I6Xdi10eY*&F8}}l diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e8be595..03bc515 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 65dcd68..79a61d4 100755 --- a/gradlew +++ b/gradlew @@ -144,7 +144,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +152,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac From 9b1c16c5a5572b453807e6d40651b0b62b6d170f Mon Sep 17 00:00:00 2001 From: skydoves Date: Sun, 1 Oct 2023 18:04:33 +0900 Subject: [PATCH 2/2] Fix bordoer for BrightnessSlider not showing --- .../colorpickercomposedemo/MainActivity.kt | 8 +- .../colorpickercomposedemo/MainScreen.kt | 122 ++--- .../colorpickercomposedemo/PhotoPickerIcon.kt | 56 +- .../HsvColorPickerColoredSelectorScreen.kt | 112 ++-- .../screens/ImageColorPickerScreen.kt | 108 ++-- .../colorpicker/compose/AlphaSlider.kt | 326 +++++------ .../skydoves/colorpicker/compose/AlphaTile.kt | 106 ++-- .../colorpicker/compose/AlphaTileDrawable.kt | 90 +-- .../colorpicker/compose/BitmapCalculator.kt | 64 +-- .../colorpicker/compose/BrightnessSlider.kt | 300 +++++----- .../colorpicker/compose/ColorEnvelope.kt | 6 +- .../colorpicker/compose/ColorExtensions.kt | 14 +- .../compose/ColorPickerController.kt | 512 +++++++++--------- .../compose/DrawScopeExtensions.kt | 26 +- .../colorpicker/compose/HsvBitmapDrawable.kt | 100 ++-- .../colorpicker/compose/HsvColorPicker.kt | 250 ++++----- .../colorpicker/compose/ImageColorPicker.kt | 220 ++++---- .../compose/PaletteContentScale.kt | 34 +- .../colorpicker/compose/PointMapper.kt | 90 +-- spotless.gradle | 2 +- 20 files changed, 1276 insertions(+), 1270 deletions(-) diff --git a/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/MainActivity.kt b/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/MainActivity.kt index 657b6b2..2c88dc9 100644 --- a/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/MainActivity.kt +++ b/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/MainActivity.kt @@ -21,9 +21,9 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) - setContent { MainScreen() } - } + setContent { MainScreen() } + } } diff --git a/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/MainScreen.kt b/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/MainScreen.kt index 9f88bc3..b1f0055 100644 --- a/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/MainScreen.kt +++ b/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/MainScreen.kt @@ -46,82 +46,82 @@ import com.github.skydoves.colorpickercomposedemo.screens.HsvColorPickerColoredS import com.github.skydoves.colorpickercomposedemo.screens.ImageColorPickerScreen sealed class Screen(val route: String, val name: String, @DrawableRes val drawable: Int) { - object ImageColorPicker : Screen("image_picker", "Image", R.drawable.image_24px) - object HsvPicker : Screen("hsv_picker", "HSV", R.drawable.palette_24px) + object ImageColorPicker : Screen("image_picker", "Image", R.drawable.image_24px) + object HsvPicker : Screen("hsv_picker", "HSV", R.drawable.palette_24px) } val navigationItems = listOf( - Screen.ImageColorPicker, - Screen.HsvPicker, + Screen.ImageColorPicker, + Screen.HsvPicker, ) @Composable fun MainScreen() { - val navController = rememberNavController() - Scaffold( - bottomBar = { BottomBar(navController) }, - topBar = { MainToolBar() }, - ) { innerPadding -> - NavHost( - navController, - startDestination = Screen.ImageColorPicker.route, - Modifier.padding(innerPadding), - ) { - composable(Screen.ImageColorPicker.route) { - ImageColorPickerScreen() - } - composable(Screen.HsvPicker.route) { - HsvColorPickerColoredSelectorScreen() - } - } + val navController = rememberNavController() + Scaffold( + bottomBar = { BottomBar(navController) }, + topBar = { MainToolBar() }, + ) { innerPadding -> + NavHost( + navController, + startDestination = Screen.ImageColorPicker.route, + Modifier.padding(innerPadding), + ) { + composable(Screen.ImageColorPicker.route) { + ImageColorPickerScreen() + } + composable(Screen.HsvPicker.route) { + HsvColorPickerColoredSelectorScreen() + } } + } } @Composable fun MainToolBar() { - TopAppBar( - elevation = 6.dp, - backgroundColor = Color(0xFF6200EE), - modifier = Modifier.height(58.dp), - ) { - Text( - modifier = Modifier - .padding(8.dp) - .align(Alignment.CenterVertically), - text = stringResource(R.string.app_name), - color = Color.White, - fontSize = 18.sp, - fontWeight = FontWeight.Bold, - ) - } + TopAppBar( + elevation = 6.dp, + backgroundColor = Color(0xFF6200EE), + modifier = Modifier.height(58.dp), + ) { + Text( + modifier = Modifier + .padding(8.dp) + .align(Alignment.CenterVertically), + text = stringResource(R.string.app_name), + color = Color.White, + fontSize = 18.sp, + fontWeight = FontWeight.Bold, + ) + } } @Composable fun BottomBar(navController: NavController) { - BottomNavigation { - val navBackStackEntry by navController.currentBackStackEntryAsState() - val currentDestination = navBackStackEntry?.destination - navigationItems.forEach { screen -> - BottomNavigationItem( - icon = { Icon(painterResource(id = screen.drawable), contentDescription = null) }, - label = { Text(screen.name) }, - selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true, - onClick = { - navController.navigate(screen.route) { - // Pop up to the start destination of the graph to - // avoid building up a large stack of destinations - // on the back stack as users select items - popUpTo(navController.graph.findStartDestination().id) { - saveState = true - } - // Avoid multiple copies of the same destination when - // reselecting the same item - launchSingleTop = true - // Restore state when reselecting a previously selected item - restoreState = true - } - }, - ) - } + BottomNavigation { + val navBackStackEntry by navController.currentBackStackEntryAsState() + val currentDestination = navBackStackEntry?.destination + navigationItems.forEach { screen -> + BottomNavigationItem( + icon = { Icon(painterResource(id = screen.drawable), contentDescription = null) }, + label = { Text(screen.name) }, + selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true, + onClick = { + navController.navigate(screen.route) { + // Pop up to the start destination of the graph to + // avoid building up a large stack of destinations + // on the back stack as users select items + popUpTo(navController.graph.findStartDestination().id) { + saveState = true + } + // Avoid multiple copies of the same destination when + // reselecting the same item + launchSingleTop = true + // Restore state when reselecting a previously selected item + restoreState = true + } + }, + ) } + } } diff --git a/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/PhotoPickerIcon.kt b/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/PhotoPickerIcon.kt index acd9a3d..c794d40 100644 --- a/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/PhotoPickerIcon.kt +++ b/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/PhotoPickerIcon.kt @@ -41,36 +41,36 @@ import com.google.modernstorage.photopicker.PhotoPicker @Composable @SuppressLint("UnsafeOptInUsageError") fun ColumnScope.PhotoPickerIcon( - controller: ColorPickerController, + controller: ColorPickerController, ) { - val context = LocalContext.current - val photoPicker = - rememberLauncherForActivityResult(PhotoPicker()) { uris -> - val uri = uris.firstOrNull() ?: return@rememberLauncherForActivityResult + val context = LocalContext.current + val photoPicker = + rememberLauncherForActivityResult(PhotoPicker()) { uris -> + val uri = uris.firstOrNull() ?: return@rememberLauncherForActivityResult - val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - ImageDecoder.decodeBitmap(ImageDecoder.createSource(context.contentResolver, uri)) - } else { - MediaStore.Images.Media.getBitmap(context.contentResolver, uri) - } + val bitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + ImageDecoder.decodeBitmap(ImageDecoder.createSource(context.contentResolver, uri)) + } else { + MediaStore.Images.Media.getBitmap(context.contentResolver, uri) + } - controller.setPaletteImageBitmap(bitmap.asImageBitmap()) - } - - Box( - modifier = Modifier - .padding(horizontal = 16.dp) - .align(Alignment.End), - ) { - Image( - modifier = Modifier - .size(42.dp) - .clickable { - // Launch the picker with only one image selectable - photoPicker.launch(PhotoPicker.Args(PhotoPicker.Type.IMAGES_ONLY, 1)) - }, - imageVector = ImageVector.vectorResource(R.drawable.ic_gallery), - contentDescription = null, - ) + controller.setPaletteImageBitmap(bitmap.asImageBitmap()) } + + Box( + modifier = Modifier + .padding(horizontal = 16.dp) + .align(Alignment.End), + ) { + Image( + modifier = Modifier + .size(42.dp) + .clickable { + // Launch the picker with only one image selectable + photoPicker.launch(PhotoPicker.Args(PhotoPicker.Type.IMAGES_ONLY, 1)) + }, + imageVector = ImageVector.vectorResource(R.drawable.ic_gallery), + contentDescription = null, + ) + } } diff --git a/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/screens/HsvColorPickerColoredSelectorScreen.kt b/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/screens/HsvColorPickerColoredSelectorScreen.kt index 3c3bf6c..21d2a2e 100644 --- a/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/screens/HsvColorPickerColoredSelectorScreen.kt +++ b/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/screens/HsvColorPickerColoredSelectorScreen.kt @@ -48,66 +48,66 @@ import com.github.skydoves.colorpicker.compose.rememberColorPickerController @Preview @Composable fun HsvColorPickerColoredSelectorScreen() { - val controller = rememberColorPickerController() - var hexCode by remember { mutableStateOf("") } - var textColor by remember { mutableStateOf(Color.Transparent) } + val controller = rememberColorPickerController() + var hexCode by remember { mutableStateOf("") } + var textColor by remember { mutableStateOf(Color.Transparent) } - Column { - Spacer(modifier = Modifier.weight(1f)) + Column { + Spacer(modifier = Modifier.weight(1f)) - Box(modifier = Modifier.weight(8f)) { - HsvColorPicker( - modifier = Modifier - .padding(10.dp), - controller = controller, - drawOnPosSelected = { - drawColorIndicator( - controller.selectedPoint.value, - controller.selectedColor.value, - ) - }, - onColorChanged = { colorEnvelope -> - hexCode = colorEnvelope.hexCode - textColor = colorEnvelope.color - }, - initialColor = Color.Red, - ) - } + Box(modifier = Modifier.weight(8f)) { + HsvColorPicker( + modifier = Modifier + .padding(10.dp), + controller = controller, + drawOnPosSelected = { + drawColorIndicator( + controller.selectedPoint.value, + controller.selectedColor.value, + ) + }, + onColorChanged = { colorEnvelope -> + hexCode = colorEnvelope.hexCode + textColor = colorEnvelope.color + }, + initialColor = Color.Red, + ) + } - Spacer(modifier = Modifier.weight(1f)) + Spacer(modifier = Modifier.weight(1f)) - AlphaSlider( - modifier = Modifier - .fillMaxWidth() - .padding(10.dp) - .height(35.dp) - .align(Alignment.CenterHorizontally), - controller = controller, - ) + AlphaSlider( + modifier = Modifier + .fillMaxWidth() + .padding(10.dp) + .height(35.dp) + .align(Alignment.CenterHorizontally), + controller = controller, + ) - BrightnessSlider( - modifier = Modifier - .fillMaxWidth() - .padding(10.dp) - .height(35.dp) - .align(Alignment.CenterHorizontally), - controller = controller, - ) + BrightnessSlider( + modifier = Modifier + .fillMaxWidth() + .padding(10.dp) + .height(35.dp) + .align(Alignment.CenterHorizontally), + controller = controller, + ) - Text( - text = "#$hexCode", - color = textColor, - fontSize = 16.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.align(Alignment.CenterHorizontally), - ) - AlphaTile( - modifier = Modifier - .size(80.dp) - .clip(RoundedCornerShape(6.dp)) - .align(Alignment.CenterHorizontally), - controller = controller, - ) - Spacer(modifier = Modifier.weight(1f)) - } + Text( + text = "#$hexCode", + color = textColor, + fontSize = 16.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier.align(Alignment.CenterHorizontally), + ) + AlphaTile( + modifier = Modifier + .size(80.dp) + .clip(RoundedCornerShape(6.dp)) + .align(Alignment.CenterHorizontally), + controller = controller, + ) + Spacer(modifier = Modifier.weight(1f)) + } } diff --git a/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/screens/ImageColorPickerScreen.kt b/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/screens/ImageColorPickerScreen.kt index 0e6c62a..f3ab27a 100644 --- a/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/screens/ImageColorPickerScreen.kt +++ b/app/src/main/kotlin/com/github/skydoves/colorpickercomposedemo/screens/ImageColorPickerScreen.kt @@ -49,66 +49,70 @@ import com.github.skydoves.colorpickercomposedemo.R @Composable fun ImageColorPickerScreen() { - val controller = rememberColorPickerController() - var hexCode by remember { mutableStateOf("") } - var textColor by remember { mutableStateOf(Color.Transparent) } + val controller = rememberColorPickerController() + var hexCode by remember { mutableStateOf("") } + var textColor by remember { mutableStateOf(Color.Transparent) } - Column { - Spacer(modifier = Modifier.weight(1f)) + Column { + Spacer(modifier = Modifier.weight(1f)) - PhotoPickerIcon(controller) + PhotoPickerIcon(controller) - ImageColorPicker( - modifier = Modifier - .fillMaxWidth() - .height(200.dp) - .padding(10.dp), - controller = controller, - paletteImageBitmap = ImageBitmap.imageResource(R.drawable.palettebar), - onColorChanged = { colorEnvelope: ColorEnvelope -> - hexCode = colorEnvelope.hexCode - textColor = colorEnvelope.color - }, - ) + ImageColorPicker( + modifier = Modifier + .fillMaxWidth() + .height(200.dp) + .padding(10.dp), + controller = controller, + paletteImageBitmap = ImageBitmap.imageResource(R.drawable.palettebar), + onColorChanged = { colorEnvelope: ColorEnvelope -> + hexCode = colorEnvelope.hexCode + textColor = colorEnvelope.color + }, + ) - Spacer(modifier = Modifier.weight(5f)) + Spacer(modifier = Modifier.weight(5f)) - AlphaSlider( - modifier = Modifier - .fillMaxWidth() - .padding(10.dp) - .height(35.dp) - .align(Alignment.CenterHorizontally), - controller = controller, - ) + AlphaSlider( + modifier = Modifier + .fillMaxWidth() + .padding(10.dp) + .height(35.dp) + .align(Alignment.CenterHorizontally), + borderColor = Color.Yellow, + borderSize = 10.dp, + controller = controller, + ) - BrightnessSlider( - modifier = Modifier - .fillMaxWidth() - .padding(10.dp) - .height(35.dp) - .align(Alignment.CenterHorizontally), - controller = controller, - ) + BrightnessSlider( + modifier = Modifier + .fillMaxWidth() + .padding(10.dp) + .height(35.dp) + .align(Alignment.CenterHorizontally), + borderColor = Color.Yellow, + borderSize = 10.dp, + controller = controller, + ) - Spacer(modifier = Modifier.weight(3f)) + Spacer(modifier = Modifier.weight(3f)) - Text( - text = "#$hexCode", - color = textColor, - fontSize = 16.sp, - fontWeight = FontWeight.Bold, - modifier = Modifier.align(Alignment.CenterHorizontally), - ) + Text( + text = "#$hexCode", + color = textColor, + fontSize = 16.sp, + fontWeight = FontWeight.Bold, + modifier = Modifier.align(Alignment.CenterHorizontally), + ) - AlphaTile( - modifier = Modifier - .size(80.dp) - .clip(RoundedCornerShape(6.dp)) - .align(Alignment.CenterHorizontally), - controller = controller, - ) + AlphaTile( + modifier = Modifier + .size(80.dp) + .clip(RoundedCornerShape(6.dp)) + .align(Alignment.CenterHorizontally), + controller = controller, + ) - Spacer(modifier = Modifier.height(50.dp)) - } + Spacer(modifier = Modifier.height(50.dp)) + } } diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/AlphaSlider.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/AlphaSlider.kt index 85f6d61..7cc4cda 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/AlphaSlider.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/AlphaSlider.kt @@ -69,174 +69,174 @@ import androidx.compose.ui.unit.dp */ @Composable public fun AlphaSlider( - modifier: Modifier = Modifier, - controller: ColorPickerController, - borderRadius: Dp = 6.dp, - borderSize: Dp = 5.dp, - borderColor: Color = Color.LightGray, - wheelImageBitmap: ImageBitmap? = null, - wheelRadius: Dp = 12.dp, - wheelColor: Color = Color.White, - @FloatRange(from = 0.0, to = 1.0) wheelAlpha: Float = 1.0f, - wheelPaint: Paint = Paint().apply { - color = wheelColor - alpha = wheelAlpha - }, - tileOddColor: Color = defaultTileOddColor, - tileEvenColor: Color = defaultTileEvenColor, - tileSize: Dp = 12.dp, - initialColor: Color? = null, + modifier: Modifier = Modifier, + controller: ColorPickerController, + borderRadius: Dp = 6.dp, + borderSize: Dp = 5.dp, + borderColor: Color = Color.LightGray, + wheelImageBitmap: ImageBitmap? = null, + wheelRadius: Dp = 12.dp, + wheelColor: Color = Color.White, + @FloatRange(from = 0.0, to = 1.0) wheelAlpha: Float = 1.0f, + wheelPaint: Paint = Paint().apply { + color = wheelColor + alpha = wheelAlpha + }, + tileOddColor: Color = defaultTileOddColor, + tileEvenColor: Color = defaultTileEvenColor, + tileSize: Dp = 12.dp, + initialColor: Color? = null, ) { - val density = LocalDensity.current - var backgroundBitmap: ImageBitmap? = null - var bitmapSize = IntSize(0, 0) - val borderPaint: Paint = Paint().apply { - style = PaintingStyle.Stroke - strokeWidth = with(LocalDensity.current) { borderSize.toPx() } - color = borderColor - } - val colorPaint: Paint = Paint().apply { - color = controller.pureSelectedColor.value - } - var isInitialized by remember { mutableStateOf(false) } + val density = LocalDensity.current + var backgroundBitmap: ImageBitmap? = null + var bitmapSize = IntSize(0, 0) + val borderPaint: Paint = Paint().apply { + style = PaintingStyle.Stroke + strokeWidth = with(LocalDensity.current) { borderSize.toPx() } + color = borderColor + } + val colorPaint: Paint = Paint().apply { + color = controller.pureSelectedColor.value + } + var isInitialized by remember { mutableStateOf(false) } - SideEffect { - controller.isAttachedAlphaSlider = true - } + SideEffect { + controller.isAttachedAlphaSlider = true + } - Canvas( - modifier = modifier - .fillMaxWidth() - .clip(RoundedCornerShape(borderRadius)) - .onSizeChanged { newSize -> - val size = - newSize.takeIf { it.width != 0 && it.height != 0 } ?: return@onSizeChanged - val drawable = AlphaTileDrawable( - with(density) { tileSize.toPx() }, - tileOddColor, - tileEvenColor, - ) - backgroundBitmap - ?.asAndroidBitmap() - ?.recycle() - backgroundBitmap = - ImageBitmap(size.width, size.height, ImageBitmapConfig.Argb8888).apply { - val backgroundCanvas = Canvas(this) - drawable.setBounds( - 0, - 0, - backgroundCanvas.nativeCanvas.width, - backgroundCanvas.nativeCanvas.height, - ) - drawable.draw(backgroundCanvas.nativeCanvas) - backgroundCanvas.drawRoundRect( - left = 0f, - top = 0f, - right = size.width.toFloat(), - bottom = size.height.toFloat(), - radiusX = borderRadius.value, - radiusY = borderRadius.value, - paint = borderPaint, - ) - } - bitmapSize = size - } - .pointerInput(Unit) { - detectHorizontalDragGestures { change, _ -> - val wheelPoint = change.position.x - val position: Float = if (wheelImageBitmap == null) { - val point = wheelPoint.coerceIn( - minimumValue = 0f, - maximumValue = bitmapSize.width.toFloat(), - ) - point / bitmapSize.width - } else { - val point = wheelPoint.coerceIn( - minimumValue = 0f, - maximumValue = bitmapSize.width.toFloat(), - ) - point / bitmapSize.width - } - controller.setAlpha(position.coerceIn(0f, 1f), fromUser = true) - } - } - .pointerInput(Unit) { - detectTapGestures { offset -> - val wheelPoint = offset.x - val position: Float = if (wheelImageBitmap == null) { - val point = wheelPoint.coerceIn( - minimumValue = 0f, - maximumValue = bitmapSize.width.toFloat(), - ) - point / bitmapSize.width - } else { - val point = wheelPoint.coerceIn( - minimumValue = 0f, - maximumValue = bitmapSize.width.toFloat(), - ) - point / bitmapSize.width - } - controller.setAlpha(position.coerceIn(0f, 1f), fromUser = true) - } - }, - ) { - drawIntoCanvas { canvas -> - backgroundBitmap?.let { - // draw background bitmap. - canvas.drawImage(it, Offset.Zero, Paint()) + Canvas( + modifier = modifier + .fillMaxWidth() + .clip(RoundedCornerShape(borderRadius)) + .onSizeChanged { newSize -> + val size = + newSize.takeIf { it.width != 0 && it.height != 0 } ?: return@onSizeChanged + val drawable = AlphaTileDrawable( + with(density) { tileSize.toPx() }, + tileOddColor, + tileEvenColor, + ) + backgroundBitmap + ?.asAndroidBitmap() + ?.recycle() + backgroundBitmap = + ImageBitmap(size.width, size.height, ImageBitmapConfig.Argb8888).apply { + val backgroundCanvas = Canvas(this) + drawable.setBounds( + 0, + 0, + backgroundCanvas.nativeCanvas.width, + backgroundCanvas.nativeCanvas.height, + ) + drawable.draw(backgroundCanvas.nativeCanvas) + backgroundCanvas.drawRoundRect( + left = 0f, + top = 0f, + right = size.width.toFloat(), + bottom = size.height.toFloat(), + radiusX = borderRadius.value, + radiusY = borderRadius.value, + paint = borderPaint, + ) + } + bitmapSize = size + } + .pointerInput(Unit) { + detectHorizontalDragGestures { change, _ -> + val wheelPoint = change.position.x + val position: Float = if (wheelImageBitmap == null) { + val point = wheelPoint.coerceIn( + minimumValue = 0f, + maximumValue = bitmapSize.width.toFloat(), + ) + point / bitmapSize.width + } else { + val point = wheelPoint.coerceIn( + minimumValue = 0f, + maximumValue = bitmapSize.width.toFloat(), + ) + point / bitmapSize.width + } + controller.setAlpha(position.coerceIn(0f, 1f), fromUser = true) + } + } + .pointerInput(Unit) { + detectTapGestures { offset -> + val wheelPoint = offset.x + val position: Float = if (wheelImageBitmap == null) { + val point = wheelPoint.coerceIn( + minimumValue = 0f, + maximumValue = bitmapSize.width.toFloat(), + ) + point / bitmapSize.width + } else { + val point = wheelPoint.coerceIn( + minimumValue = 0f, + maximumValue = bitmapSize.width.toFloat(), + ) + point / bitmapSize.width + } + controller.setAlpha(position.coerceIn(0f, 1f), fromUser = true) + } + }, + ) { + drawIntoCanvas { canvas -> + backgroundBitmap?.let { + // draw background bitmap. + canvas.drawImage(it, Offset.Zero, Paint()) - // draw a linear gradient color shader. - val startColor = controller.pureSelectedColor.value.copy(alpha = 0f) - val endColor = controller.pureSelectedColor.value.copy(alpha = 1f) - val shader = LinearGradientShader( - colors = listOf(startColor, endColor), - from = Offset.Zero, - to = Offset(bitmapSize.width.toFloat(), bitmapSize.height.toFloat()), - tileMode = TileMode.Clamp, - ) - colorPaint.shader = shader - canvas.drawRoundRect( - left = 0f, - top = 0f, - right = bitmapSize.width.toFloat(), - bottom = bitmapSize.height.toFloat(), - radiusX = borderRadius.value, - radiusY = borderRadius.value, - paint = colorPaint, - ) + // draw a linear gradient color shader. + val startColor = controller.pureSelectedColor.value.copy(alpha = 0f) + val endColor = controller.pureSelectedColor.value.copy(alpha = 1f) + val shader = LinearGradientShader( + colors = listOf(startColor, endColor), + from = Offset.Zero, + to = Offset(bitmapSize.width.toFloat(), bitmapSize.height.toFloat()), + tileMode = TileMode.Clamp, + ) + colorPaint.shader = shader + canvas.drawRoundRect( + left = 0f, + top = 0f, + right = bitmapSize.width.toFloat(), + bottom = bitmapSize.height.toFloat(), + radiusX = borderRadius.value, + radiusY = borderRadius.value, + paint = colorPaint, + ) - // draw wheel bitmap on the canvas. - if (wheelImageBitmap == null) { - val position = controller.alpha.value - val point = (bitmapSize.width * position).coerceIn( - minimumValue = 0f, - maximumValue = bitmapSize.width.toFloat(), - ) - canvas.drawCircle( - Offset(x = point, y = bitmapSize.height / 2f), - wheelRadius.toPx(), - wheelPaint, - ) - } else { - val position = controller.alpha.value - val point = (bitmapSize.width * position).coerceIn( - minimumValue = 0f, - maximumValue = bitmapSize.width.toFloat(), - ) - canvas.drawImage( - wheelImageBitmap, - Offset( - x = point - (wheelImageBitmap.width / 2), - y = bitmapSize.height / 2f - wheelImageBitmap.height / 2, - ), - Paint(), - ) - } - } - if (initialColor != null && !isInitialized) { - isInitialized = true - controller.setAlpha(alpha = initialColor.alpha, fromUser = false) - } + // draw wheel bitmap on the canvas. + if (wheelImageBitmap == null) { + val position = controller.alpha.value + val point = (bitmapSize.width * position).coerceIn( + minimumValue = 0f, + maximumValue = bitmapSize.width.toFloat(), + ) + canvas.drawCircle( + Offset(x = point, y = bitmapSize.height / 2f), + wheelRadius.toPx(), + wheelPaint, + ) + } else { + val position = controller.alpha.value + val point = (bitmapSize.width * position).coerceIn( + minimumValue = 0f, + maximumValue = bitmapSize.width.toFloat(), + ) + canvas.drawImage( + wheelImageBitmap, + Offset( + x = point - (wheelImageBitmap.width / 2), + y = bitmapSize.height / 2f - wheelImageBitmap.height / 2, + ), + Paint(), + ) } + } + if (initialColor != null && !isInitialized) { + isInitialized = true + controller.setAlpha(alpha = initialColor.alpha, fromUser = false) + } } + } } diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/AlphaTile.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/AlphaTile.kt index f6ec81e..39602ae 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/AlphaTile.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/AlphaTile.kt @@ -47,60 +47,60 @@ import androidx.compose.ui.unit.dp */ @Composable public fun AlphaTile( - modifier: Modifier, - controller: ColorPickerController? = null, - selectedColor: Color = Color.Transparent, - tileOddColor: Color = defaultTileOddColor, - tileEvenColor: Color = defaultTileEvenColor, - tileSize: Dp = 12.dp, + modifier: Modifier, + controller: ColorPickerController? = null, + selectedColor: Color = Color.Transparent, + tileOddColor: Color = defaultTileOddColor, + tileEvenColor: Color = defaultTileEvenColor, + tileSize: Dp = 12.dp, ) { - val density = LocalDensity.current - var backgroundBitmap: ImageBitmap? = null - var bitmapSize = IntSize(0, 0) - val colorPaint: Paint = Paint().apply { - this.color = controller?.selectedColor?.value ?: selectedColor - } + val density = LocalDensity.current + var backgroundBitmap: ImageBitmap? = null + var bitmapSize = IntSize(0, 0) + val colorPaint: Paint = Paint().apply { + this.color = controller?.selectedColor?.value ?: selectedColor + } - Canvas( - modifier = modifier - .fillMaxSize() - .onSizeChanged { newSize -> - val size = - newSize.takeIf { it.width != 0 && it.height != 0 } ?: return@onSizeChanged - val drawable = - AlphaTileDrawable( - with(density) { tileSize.toPx() }, - tileOddColor, - tileEvenColor, - ) - backgroundBitmap - ?.asAndroidBitmap() - ?.recycle() - backgroundBitmap = - ImageBitmap(size.width, size.height, ImageBitmapConfig.Argb8888).apply { - val backgroundCanvas = Canvas(this) - drawable.setBounds( - 0, - 0, - backgroundCanvas.nativeCanvas.width, - backgroundCanvas.nativeCanvas.height, - ) - drawable.draw(backgroundCanvas.nativeCanvas) - } - bitmapSize = size - }, - ) { - drawIntoCanvas { canvas -> - backgroundBitmap?.let { - canvas.drawImage(it, Offset.Zero, Paint()) - canvas.drawRect( - 0f, - 0f, - bitmapSize.width.toFloat(), - bitmapSize.height.toFloat(), - colorPaint, - ) - } - } + Canvas( + modifier = modifier + .fillMaxSize() + .onSizeChanged { newSize -> + val size = + newSize.takeIf { it.width != 0 && it.height != 0 } ?: return@onSizeChanged + val drawable = + AlphaTileDrawable( + with(density) { tileSize.toPx() }, + tileOddColor, + tileEvenColor, + ) + backgroundBitmap + ?.asAndroidBitmap() + ?.recycle() + backgroundBitmap = + ImageBitmap(size.width, size.height, ImageBitmapConfig.Argb8888).apply { + val backgroundCanvas = Canvas(this) + drawable.setBounds( + 0, + 0, + backgroundCanvas.nativeCanvas.width, + backgroundCanvas.nativeCanvas.height, + ) + drawable.draw(backgroundCanvas.nativeCanvas) + } + bitmapSize = size + }, + ) { + drawIntoCanvas { canvas -> + backgroundBitmap?.let { + canvas.drawImage(it, Offset.Zero, Paint()) + canvas.drawRect( + 0f, + 0f, + bitmapSize.width.toFloat(), + bitmapSize.height.toFloat(), + colorPaint, + ) + } } + } } diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/AlphaTileDrawable.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/AlphaTileDrawable.kt index 0482c8a..47a0fe3 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/AlphaTileDrawable.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/AlphaTileDrawable.kt @@ -38,61 +38,61 @@ import androidx.compose.ui.graphics.asAndroidBitmap * @param tileEvenColor Color of the even tiles. */ public class AlphaTileDrawable constructor( - tileSize: Float, - tileOddColor: Color, - tileEvenColor: Color, + tileSize: Float, + tileOddColor: Color, + tileEvenColor: Color, ) : Drawable() { - private val androidPaint: android.graphics.Paint = android.graphics.Paint( - android.graphics.Paint.ANTI_ALIAS_FLAG, - ) + private val androidPaint: android.graphics.Paint = android.graphics.Paint( + android.graphics.Paint.ANTI_ALIAS_FLAG, + ) - init { - val size = tileSize.toInt() - val imageBitmap = ImageBitmap(size * 2, size * 2, ImageBitmapConfig.Argb8888) - val canvas = Canvas(imageBitmap) - val rect = Rect(0f, 0f, tileSize, tileSize) + init { + val size = tileSize.toInt() + val imageBitmap = ImageBitmap(size * 2, size * 2, ImageBitmapConfig.Argb8888) + val canvas = Canvas(imageBitmap) + val rect = Rect(0f, 0f, tileSize, tileSize) - val bitmapPaint = Paint().apply { - style = PaintingStyle.Fill - isAntiAlias = true - } + val bitmapPaint = Paint().apply { + style = PaintingStyle.Fill + isAntiAlias = true + } - bitmapPaint.color = tileOddColor - drawTile(canvas, rect, bitmapPaint, 0f, 0f) - drawTile(canvas, rect, bitmapPaint, tileSize, tileSize) + bitmapPaint.color = tileOddColor + drawTile(canvas, rect, bitmapPaint, 0f, 0f) + drawTile(canvas, rect, bitmapPaint, tileSize, tileSize) - bitmapPaint.color = tileEvenColor - drawTile(canvas, rect, bitmapPaint, 0f, tileSize) - drawTile(canvas, rect, bitmapPaint, tileSize, 0f) + bitmapPaint.color = tileEvenColor + drawTile(canvas, rect, bitmapPaint, 0f, tileSize) + drawTile(canvas, rect, bitmapPaint, tileSize, 0f) - androidPaint.shader = BitmapShader( - imageBitmap.asAndroidBitmap(), - Shader.TileMode.REPEAT, - Shader.TileMode.REPEAT, - ) - } + androidPaint.shader = BitmapShader( + imageBitmap.asAndroidBitmap(), + Shader.TileMode.REPEAT, + Shader.TileMode.REPEAT, + ) + } - private fun drawTile(canvas: Canvas, rect: Rect, paint: Paint, dx: Float, dy: Float) { - val translated = rect.translate(dx, dy) - canvas.drawRect(translated, paint) - } + private fun drawTile(canvas: Canvas, rect: Rect, paint: Paint, dx: Float, dy: Float) { + val translated = rect.translate(dx, dy) + canvas.drawRect(translated, paint) + } - override fun draw(canvas: android.graphics.Canvas) { - canvas.drawPaint(androidPaint) - } + override fun draw(canvas: android.graphics.Canvas) { + canvas.drawPaint(androidPaint) + } - override fun setAlpha(alpha: Int) { - androidPaint.alpha = alpha - } + override fun setAlpha(alpha: Int) { + androidPaint.alpha = alpha + } - override fun setColorFilter(colorFilter: ColorFilter?) { - androidPaint.colorFilter = colorFilter - } + override fun setColorFilter(colorFilter: ColorFilter?) { + androidPaint.colorFilter = colorFilter + } - @Deprecated( - message = "This method will be deprecated on the future Android SDK", - replaceWith = ReplaceWith(expression = "getOpacity"), - ) - override fun getOpacity(): Int = PixelFormat.OPAQUE + @Deprecated( + message = "This method will be deprecated on the future Android SDK", + replaceWith = ReplaceWith(expression = "getOpacity"), + ) + override fun getOpacity(): Int = PixelFormat.OPAQUE } diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/BitmapCalculator.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/BitmapCalculator.kt index da44ab1..3424f20 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/BitmapCalculator.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/BitmapCalculator.kt @@ -25,39 +25,39 @@ import androidx.compose.ui.unit.IntSize */ internal object BitmapCalculator { - /** - * Scale the source with maintaining the source's aspect ratio - * so that both dimensions (width and height) of the source will be equal to or less than the - * corresponding dimension of the target size. - */ - internal fun scaleBitmap(bitmap: Bitmap, targetSize: IntSize): Bitmap { - return Bitmap.createScaledBitmap( - bitmap, - targetSize.width, - targetSize.height, - false, - ) - } + /** + * Scale the source with maintaining the source's aspect ratio + * so that both dimensions (width and height) of the source will be equal to or less than the + * corresponding dimension of the target size. + */ + internal fun scaleBitmap(bitmap: Bitmap, targetSize: IntSize): Bitmap { + return Bitmap.createScaledBitmap( + bitmap, + targetSize.width, + targetSize.height, + false, + ) + } - /** - * Crop ths source the corresponding dimension of the target size. - * so that if the dimensions (width and height) source is bigger than the target size, - * it will be cut off from the center. - */ - internal fun cropBitmap(bitmap: Bitmap, targetSize: IntSize): Bitmap { - return ThumbnailUtils.extractThumbnail(bitmap, targetSize.width, targetSize.height) - } + /** + * Crop ths source the corresponding dimension of the target size. + * so that if the dimensions (width and height) source is bigger than the target size, + * it will be cut off from the center. + */ + internal fun cropBitmap(bitmap: Bitmap, targetSize: IntSize): Bitmap { + return ThumbnailUtils.extractThumbnail(bitmap, targetSize.width, targetSize.height) + } - /** - * Scale the source with maintaining the source's aspect ratio - * so that if both dimensions (width and height) of the source is smaller than the target size, - * it will not be scaled. - */ - internal fun inside(bitmap: Bitmap, targetSize: IntSize): Bitmap { - return if (bitmap.width < targetSize.width && bitmap.height < targetSize.height) { - bitmap - } else { - scaleBitmap(bitmap, targetSize) - } + /** + * Scale the source with maintaining the source's aspect ratio + * so that if both dimensions (width and height) of the source is smaller than the target size, + * it will not be scaled. + */ + internal fun inside(bitmap: Bitmap, targetSize: IntSize): Bitmap { + return if (bitmap.width < targetSize.width && bitmap.height < targetSize.height) { + bitmap + } else { + scaleBitmap(bitmap, targetSize) } + } } diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/BrightnessSlider.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/BrightnessSlider.kt index 7dba7d5..47ec811 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/BrightnessSlider.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/BrightnessSlider.kt @@ -66,160 +66,162 @@ import kotlin.math.max */ @Composable public fun BrightnessSlider( - modifier: Modifier = Modifier, - controller: ColorPickerController, - borderRadius: Dp = 6.dp, - borderSize: Dp = 5.dp, - borderColor: Color = Color.LightGray, - wheelImageBitmap: ImageBitmap? = null, - wheelRadius: Dp = 12.dp, - wheelColor: Color = Color.White, - @FloatRange(from = 0.0, to = 1.0) wheelAlpha: Float = 1.0f, - wheelPaint: Paint = Paint().apply { - color = wheelColor - alpha = wheelAlpha - }, - initialColor: Color? = null, + modifier: Modifier = Modifier, + controller: ColorPickerController, + borderRadius: Dp = 6.dp, + borderSize: Dp = 5.dp, + borderColor: Color = Color.LightGray, + wheelImageBitmap: ImageBitmap? = null, + wheelRadius: Dp = 12.dp, + wheelColor: Color = Color.White, + @FloatRange(from = 0.0, to = 1.0) wheelAlpha: Float = 1.0f, + wheelPaint: Paint = Paint().apply { + color = wheelColor + alpha = wheelAlpha + }, + initialColor: Color? = null, ) { - var backgroundBitmap: ImageBitmap? = null - var bitmapSize = IntSize(0, 0) - val borderPaint: Paint = Paint().apply { - style = PaintingStyle.Stroke - strokeWidth = with(LocalDensity.current) { borderSize.toPx() } - color = borderColor - } - val colorPaint: Paint = Paint().apply { - color = controller.pureSelectedColor.value - } - var isInitialized by remember { mutableStateOf(false) } + var backgroundBitmap: ImageBitmap? = null + var bitmapSize = IntSize(0, 0) + val borderPaint: Paint = Paint().apply { + style = PaintingStyle.Stroke + strokeWidth = with(LocalDensity.current) { borderSize.toPx() } + color = borderColor + } + val colorPaint: Paint = Paint().apply { + color = controller.pureSelectedColor.value + } + var isInitialized by remember { mutableStateOf(false) } - SideEffect { - controller.isAttachedBrightnessSlider = true - } + SideEffect { + controller.isAttachedBrightnessSlider = true + } - Canvas( - modifier = modifier - .fillMaxWidth() - .clip(RoundedCornerShape(borderRadius)) - .onSizeChanged { newSize -> - val size = - newSize.takeIf { it.width != 0 && it.height != 0 } ?: return@onSizeChanged - backgroundBitmap - ?.asAndroidBitmap() - ?.recycle() - backgroundBitmap = - ImageBitmap(size.width, size.height, ImageBitmapConfig.Argb8888).apply { - val backgroundCanvas = Canvas(this) - backgroundCanvas.drawRoundRect( - left = 0f, - top = 0f, - right = size.width.toFloat(), - bottom = size.height.toFloat(), - radiusX = borderRadius.value, - radiusY = borderRadius.value, - paint = borderPaint, - ) - } - bitmapSize = size - } - .pointerInput(Unit) { - detectTapGestures { offset -> - // calculate wheel position. - val wheelPoint = offset.x - val position: Float = if (wheelImageBitmap == null) { - val point = wheelPoint.coerceIn( - minimumValue = 0f, - maximumValue = bitmapSize.width.toFloat(), - ) - point / bitmapSize.width - } else { - val point = wheelPoint.coerceIn( - minimumValue = 0f, - maximumValue = bitmapSize.width.toFloat(), - ) - point / bitmapSize.width - } - controller.setBrightness(position.coerceIn(0f, 1f), fromUser = true) - } - } - .pointerInput(Unit) { - detectHorizontalDragGestures { change, _ -> - // calculate wheel position. - val wheelPoint = change.position.x - val position: Float = if (wheelImageBitmap == null) { - val point = wheelPoint.coerceIn( - minimumValue = 0f, - maximumValue = bitmapSize.width.toFloat(), - ) - point / bitmapSize.width - } else { - val point = wheelPoint.coerceIn( - minimumValue = 0f, - maximumValue = bitmapSize.width.toFloat(), - ) - point / bitmapSize.width - } - controller.setBrightness(position.coerceIn(0f, 1f), fromUser = true) - } - }, - ) { - drawIntoCanvas { canvas -> - backgroundBitmap?.let { - // draw background bitmap. - canvas.drawImage(it, Offset.Zero, Paint()) + Canvas( + modifier = modifier + .fillMaxWidth() + .clip(RoundedCornerShape(borderRadius)) + .onSizeChanged { newSize -> + val size = + newSize.takeIf { it.width != 0 && it.height != 0 } ?: return@onSizeChanged + backgroundBitmap + ?.asAndroidBitmap() + ?.recycle() + backgroundBitmap = + ImageBitmap(size.width, size.height, ImageBitmapConfig.Argb8888).apply { + val backgroundCanvas = Canvas(this) + backgroundCanvas.drawRoundRect( + left = 0f, + top = 0f, + right = size.width.toFloat(), + bottom = size.height.toFloat(), + radiusX = borderRadius.value, + radiusY = borderRadius.value, + paint = borderPaint, + ) + } + bitmapSize = size + } + .pointerInput(Unit) { + detectTapGestures { offset -> + // calculate wheel position. + val wheelPoint = offset.x + val position: Float = if (wheelImageBitmap == null) { + val point = wheelPoint.coerceIn( + minimumValue = 0f, + maximumValue = bitmapSize.width.toFloat(), + ) + point / bitmapSize.width + } else { + val point = wheelPoint.coerceIn( + minimumValue = 0f, + maximumValue = bitmapSize.width.toFloat(), + ) + point / bitmapSize.width + } + controller.setBrightness(position.coerceIn(0f, 1f), fromUser = true) + } + } + .pointerInput(Unit) { + detectHorizontalDragGestures { change, _ -> + // calculate wheel position. + val wheelPoint = change.position.x + val position: Float = if (wheelImageBitmap == null) { + val point = wheelPoint.coerceIn( + minimumValue = 0f, + maximumValue = bitmapSize.width.toFloat(), + ) + point / bitmapSize.width + } else { + val point = wheelPoint.coerceIn( + minimumValue = 0f, + maximumValue = bitmapSize.width.toFloat(), + ) + point / bitmapSize.width + } + controller.setBrightness(position.coerceIn(0f, 1f), fromUser = true) + } + }, + ) { + drawIntoCanvas { canvas -> + backgroundBitmap?.let { + // draw background bitmap. + canvas.drawImage(it, Offset.Zero, Paint()) - // draw a linear gradient color shader. - val shader = LinearGradientShader( - colors = listOf(Color.Black, controller.pureSelectedColor.value), - from = Offset.Zero, - to = Offset(bitmapSize.width.toFloat(), bitmapSize.height.toFloat()), - tileMode = TileMode.Clamp, - ) - colorPaint.shader = shader - canvas.drawRoundRect( - left = 0f, - top = 0f, - right = bitmapSize.width.toFloat(), - bottom = bitmapSize.height.toFloat(), - radiusX = borderRadius.value, - radiusY = borderRadius.value, - paint = colorPaint, - ) + // draw a linear gradient color shader. + val startColor = controller.pureSelectedColor.value.copy(alpha = 0f) + val endColor = controller.pureSelectedColor.value.copy(alpha = 1f) + val shader = LinearGradientShader( + colors = listOf(startColor, endColor), + from = Offset.Zero, + to = Offset(bitmapSize.width.toFloat(), bitmapSize.height.toFloat()), + tileMode = TileMode.Clamp, + ) + colorPaint.shader = shader + canvas.drawRoundRect( + left = 0f, + top = 0f, + right = bitmapSize.width.toFloat(), + bottom = bitmapSize.height.toFloat(), + radiusX = borderRadius.value, + radiusY = borderRadius.value, + paint = colorPaint, + ) - // draw wheel bitmap on the canvas. - if (wheelImageBitmap == null) { - val position = controller.brightness.value - val point = (bitmapSize.width * position).coerceIn( - minimumValue = 0f, - maximumValue = bitmapSize.width.toFloat(), - ) - canvas.drawCircle( - Offset(x = point, y = bitmapSize.height / 2f), - wheelRadius.toPx(), - wheelPaint, - ) - } else { - val position = controller.brightness.value - val point = (bitmapSize.width * position).coerceIn( - minimumValue = 0f, - maximumValue = bitmapSize.width.toFloat(), - ) - canvas.drawImage( - wheelImageBitmap, - Offset( - x = point - (wheelImageBitmap.width / 2), - y = bitmapSize.height / 2f - wheelImageBitmap.height / 2, - ), - Paint(), - ) - } - if (initialColor != null && !isInitialized) { - isInitialized = true - val brightness = - max(max(initialColor.red, initialColor.green), initialColor.blue) - controller.setBrightness(brightness, fromUser = false) - } - } + // draw wheel bitmap on the canvas. + if (wheelImageBitmap == null) { + val position = controller.brightness.value + val point = (bitmapSize.width * position).coerceIn( + minimumValue = 0f, + maximumValue = bitmapSize.width.toFloat(), + ) + canvas.drawCircle( + Offset(x = point, y = bitmapSize.height / 2f), + wheelRadius.toPx(), + wheelPaint, + ) + } else { + val position = controller.brightness.value + val point = (bitmapSize.width * position).coerceIn( + minimumValue = 0f, + maximumValue = bitmapSize.width.toFloat(), + ) + canvas.drawImage( + wheelImageBitmap, + Offset( + x = point - (wheelImageBitmap.width / 2), + y = bitmapSize.height / 2f - wheelImageBitmap.height / 2, + ), + Paint(), + ) + } + if (initialColor != null && !isInitialized) { + isInitialized = true + val brightness = + max(max(initialColor.red, initialColor.green), initialColor.blue) + controller.setBrightness(brightness, fromUser = false) } + } } + } } diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ColorEnvelope.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ColorEnvelope.kt index c673216..9783eaa 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ColorEnvelope.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ColorEnvelope.kt @@ -28,7 +28,7 @@ import androidx.compose.ui.graphics.Color */ @Immutable public data class ColorEnvelope( - val color: Color, - val hexCode: String, - val fromUser: Boolean, + val color: Color, + val hexCode: String, + val fromUser: Boolean, ) diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ColorExtensions.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ColorExtensions.kt index 3e5c3bb..0463995 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ColorExtensions.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ColorExtensions.kt @@ -20,10 +20,10 @@ import androidx.compose.ui.graphics.Color import java.util.Locale internal val Color.hexCode: String - inline get() { - val a: Int = (alpha * 255).toInt() - val r: Int = (red * 255).toInt() - val g: Int = (green * 255).toInt() - val b: Int = (blue * 255).toInt() - return java.lang.String.format(Locale.getDefault(), "%02X%02X%02X%02X", a, r, g, b) - } + inline get() { + val a: Int = (alpha * 255).toInt() + val r: Int = (red * 255).toInt() + val g: Int = (green * 255).toInt() + val b: Int = (blue * 255).toInt() + return java.lang.String.format(Locale.getDefault(), "%02X%02X%02X%02X", a, r, g, b) + } diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ColorPickerController.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ColorPickerController.kt index b2f7141..faa9fcd 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ColorPickerController.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ColorPickerController.kt @@ -43,7 +43,7 @@ import kotlin.math.sqrt /** Creates and remembers a [ColorPickerController] on the current composer. */ @Composable public fun rememberColorPickerController(): ColorPickerController { - return remember { ColorPickerController() } + return remember { ColorPickerController() } } /** @@ -54,290 +54,290 @@ public fun rememberColorPickerController(): ColorPickerController { @Stable public class ColorPickerController { - /** An [ImageBitmap] to be drawn on the canvas as a palette. */ - internal var paletteBitmap: ImageBitmap? = null + /** An [ImageBitmap] to be drawn on the canvas as a palette. */ + internal var paletteBitmap: ImageBitmap? = null - /** An [ImageBitmap] to be drawn on the canvas as a wheel. */ - internal var wheelBitmap: ImageBitmap? = null + /** An [ImageBitmap] to be drawn on the canvas as a wheel. */ + internal var wheelBitmap: ImageBitmap? = null - private val _selectedPoint: MutableState = mutableStateOf(PointF(0f, 0f)) + private val _selectedPoint: MutableState = mutableStateOf(PointF(0f, 0f)) - /** State of [PointF], which represents the currently selected coordinate. */ - public val selectedPoint: State = _selectedPoint + /** State of [PointF], which represents the currently selected coordinate. */ + public val selectedPoint: State = _selectedPoint - private val _selectedColor: MutableState = mutableStateOf(Color.Transparent) + private val _selectedColor: MutableState = mutableStateOf(Color.Transparent) - /** State of [Color], which represents the currently selected color value with alpha and brightness. */ - public val selectedColor: State = _selectedColor + /** State of [Color], which represents the currently selected color value with alpha and brightness. */ + public val selectedColor: State = _selectedColor - /** State of [Color], which represents the currently selected color value without alpha and brightness. */ - internal var pureSelectedColor: MutableState = mutableStateOf(Color.Transparent) + /** State of [Color], which represents the currently selected color value without alpha and brightness. */ + internal var pureSelectedColor: MutableState = mutableStateOf(Color.Transparent) - /** Alpha value to be applied with the selected color. */ - internal var alpha: MutableState = mutableStateOf(1.0f) + /** Alpha value to be applied with the selected color. */ + internal var alpha: MutableState = mutableStateOf(1.0f) - /** Brightness value to be applied with the selected color. */ - internal var brightness: MutableState = mutableStateOf(1.0f) + /** Brightness value to be applied with the selected color. */ + internal var brightness: MutableState = mutableStateOf(1.0f) - /** Radius to draw default wheel. */ - internal var wheelRadius: Dp = 12.dp - private set + /** Radius to draw default wheel. */ + internal var wheelRadius: Dp = 12.dp + private set - /** Paint to draw default wheel. */ - internal var wheelPaint: Paint = Paint().apply { color = Color.White } - private set + /** Paint to draw default wheel. */ + internal var wheelPaint: Paint = Paint().apply { color = Color.White } + private set - /** Enable or not color selection. */ - private val enabled: MutableState = mutableStateOf(true) + /** Enable or not color selection. */ + private val enabled: MutableState = mutableStateOf(true) - /** Decide the content scale of the palette when draws. */ - private var paletteContentScale: PaletteContentScale = PaletteContentScale.FIT + /** Decide the content scale of the palette when draws. */ + private var paletteContentScale: PaletteContentScale = PaletteContentScale.FIT - /** Size of the measured canvas dimensions (width and height). */ - internal val canvasSize: MutableState = mutableStateOf(IntSize(0, 0)) + /** Size of the measured canvas dimensions (width and height). */ + internal val canvasSize: MutableState = mutableStateOf(IntSize(0, 0)) - /** Matrix of the [paletteBitmap], which is used to calculate pixel positions. */ - internal val imageBitmapMatrix: MutableState = mutableStateOf(Matrix()) + /** Matrix of the [paletteBitmap], which is used to calculate pixel positions. */ + internal val imageBitmapMatrix: MutableState = mutableStateOf(Matrix()) - /** Indicates if the color picker is HSV model. */ - internal var isHsvColorPalette: Boolean = false + /** Indicates if the color picker is HSV model. */ + internal var isHsvColorPalette: Boolean = false - /** Indicates if the alpha slider has been attached. */ - internal var isAttachedAlphaSlider: Boolean = false + /** Indicates if the alpha slider has been attached. */ + internal var isAttachedAlphaSlider: Boolean = false - /** Indicates if the brightness slider has been attached. */ - internal var isAttachedBrightnessSlider: Boolean = false + /** Indicates if the brightness slider has been attached. */ + internal var isAttachedBrightnessSlider: Boolean = false - internal var reviseTick = mutableStateOf(0) + internal var reviseTick = mutableStateOf(0) - internal var colorChangedTick = MutableStateFlow(null) + internal var colorChangedTick = MutableStateFlow(null) - private val debounceHandler = Handler(Looper.getMainLooper()) + private val debounceHandler = Handler(Looper.getMainLooper()) - private var debounceDuration: Long = 0L + private var debounceDuration: Long = 0L - /** Set an [ImageBitmap] to draw on the canvas as a palette. */ - public fun setPaletteImageBitmap(imageBitmap: ImageBitmap) { - val targetSize = canvasSize.value.takeIf { it.width != 0 && it.height != 0 } - ?: throw IllegalAccessException( - "Can't set an ImageBitmap before initializing the canvas", - ) - val copiedBitmap = - imageBitmap.asAndroidBitmap().copy(Bitmap.Config.ARGB_8888, false) - val resized = when (paletteContentScale) { - PaletteContentScale.FIT -> BitmapCalculator.scaleBitmap(copiedBitmap, targetSize) - PaletteContentScale.CROP -> BitmapCalculator.cropBitmap(copiedBitmap, targetSize) - } - paletteBitmap = resized.asImageBitmap() - copiedBitmap.recycle() - selectCenter(fromUser = false) - reviseTick.value++ + /** Set an [ImageBitmap] to draw on the canvas as a palette. */ + public fun setPaletteImageBitmap(imageBitmap: ImageBitmap) { + val targetSize = canvasSize.value.takeIf { it.width != 0 && it.height != 0 } + ?: throw IllegalAccessException( + "Can't set an ImageBitmap before initializing the canvas", + ) + val copiedBitmap = + imageBitmap.asAndroidBitmap().copy(Bitmap.Config.ARGB_8888, false) + val resized = when (paletteContentScale) { + PaletteContentScale.FIT -> BitmapCalculator.scaleBitmap(copiedBitmap, targetSize) + PaletteContentScale.CROP -> BitmapCalculator.cropBitmap(copiedBitmap, targetSize) } - - /** Set a [PaletteContentScale] to the palette bitmap. */ - public fun setPaletteContentScale(paletteContentScale: PaletteContentScale) { - this.paletteContentScale = paletteContentScale - } - - /** Set an [ImageBitmap] to draw on the canvas as a wheel. */ - public fun setWheelImageBitmap(imageBitmap: ImageBitmap?) { - wheelBitmap = imageBitmap - } - - /** Set a radius to draw default wheel. */ - public fun setWheelRadius(radius: Dp) { - wheelRadius = radius - reviseTick.value++ - } - - /** Set a paint to draw default wheel. */ - public fun setWheelPaint(paint: Paint) { - wheelPaint = paint - reviseTick.value++ - } - - /** Set a color for the wheel. */ - public fun setWheelColor(color: Color) { - wheelPaint.color = color - reviseTick.value++ - } - - /** Set an alpha for the wheel. */ - public fun setWheelAlpha(alpha: Float) { - wheelPaint.alpha = alpha - reviseTick.value++ - } - - /** Enable or unable color selection. */ - public fun setEnabled(enabled: Boolean) { - this.enabled.value = enabled - } - - /** Set the debounce duration. */ - public fun setDebounceDuration(duration: Long) { - debounceDuration = duration + paletteBitmap = resized.asImageBitmap() + copiedBitmap.recycle() + selectCenter(fromUser = false) + reviseTick.value++ + } + + /** Set a [PaletteContentScale] to the palette bitmap. */ + public fun setPaletteContentScale(paletteContentScale: PaletteContentScale) { + this.paletteContentScale = paletteContentScale + } + + /** Set an [ImageBitmap] to draw on the canvas as a wheel. */ + public fun setWheelImageBitmap(imageBitmap: ImageBitmap?) { + wheelBitmap = imageBitmap + } + + /** Set a radius to draw default wheel. */ + public fun setWheelRadius(radius: Dp) { + wheelRadius = radius + reviseTick.value++ + } + + /** Set a paint to draw default wheel. */ + public fun setWheelPaint(paint: Paint) { + wheelPaint = paint + reviseTick.value++ + } + + /** Set a color for the wheel. */ + public fun setWheelColor(color: Color) { + wheelPaint.color = color + reviseTick.value++ + } + + /** Set an alpha for the wheel. */ + public fun setWheelAlpha(alpha: Float) { + wheelPaint.alpha = alpha + reviseTick.value++ + } + + /** Enable or unable color selection. */ + public fun setEnabled(enabled: Boolean) { + this.enabled.value = enabled + } + + /** Set the debounce duration. */ + public fun setDebounceDuration(duration: Long) { + debounceDuration = duration + } + + /** + * Select a specific point by coordinates and update a selected color. + * + * @param x x-coordinate to extract a pixel color. + * @param y y-coordinate to extract a pixel color. + * @param fromUser Represents this event is triggered by user or not. + */ + public fun selectByCoordinate(x: Float, y: Float, fromUser: Boolean) { + enabled.value.takeIf { it } ?: return + val snapPoint = PointMapper.getColorPoint(this, PointF(x, y)) + val extractedColor = if (isHsvColorPalette) { + extractPixelHsvColor(snapPoint.x, snapPoint.y) + } else { + extractPixelColor(snapPoint.x, snapPoint.y) } - - /** - * Select a specific point by coordinates and update a selected color. - * - * @param x x-coordinate to extract a pixel color. - * @param y y-coordinate to extract a pixel color. - * @param fromUser Represents this event is triggered by user or not. - */ - public fun selectByCoordinate(x: Float, y: Float, fromUser: Boolean) { - enabled.value.takeIf { it } ?: return - val snapPoint = PointMapper.getColorPoint(this, PointF(x, y)) - val extractedColor = if (isHsvColorPalette) { - extractPixelHsvColor(snapPoint.x, snapPoint.y) - } else { - extractPixelColor(snapPoint.x, snapPoint.y) - } - if (extractedColor != Color.Transparent) { - // set the extracted color. - pureSelectedColor.value = extractedColor - _selectedPoint.value = PointF(snapPoint.x, snapPoint.y) - _selectedColor.value = applyHSVFactors(extractedColor) - - // notify color changes to the listeners. - if (fromUser && debounceDuration != 0L) { - notifyColorChangedWithDebounce(fromUser) - } else { - notifyColorChanged(fromUser) - } - } - } - - /** - * Select center point of the palette. - * - * @param fromUser Represents this event is triggered by user or not. - */ - public fun selectCenter(fromUser: Boolean) { - val size = canvasSize.value - selectByCoordinate(size.width * 0.5f, size.height * 0.5f, fromUser) - } - - /** Notify color changes to the color picker and other subcomponents. */ - private fun notifyColorChanged(fromUser: Boolean) { - val color = _selectedColor.value - colorChangedTick.value = ColorEnvelope(color, color.hexCode, fromUser) - } - - /** Notify color changes to the color picker and other subcomponents with debounce duration. */ - private fun notifyColorChangedWithDebounce(fromUser: Boolean) { - val runnable = { notifyColorChanged(fromUser) } - debounceHandler.removeCallbacksAndMessages(null) - debounceHandler.postDelayed(runnable, debounceDuration) - } - - /** Combine the alpha value to the selected pure color. */ - internal fun setAlpha(alpha: Float, fromUser: Boolean) { - this.alpha.value = alpha - _selectedColor.value = selectedColor.value.copy(alpha = alpha) + if (extractedColor != Color.Transparent) { + // set the extracted color. + pureSelectedColor.value = extractedColor + _selectedPoint.value = PointF(snapPoint.x, snapPoint.y) + _selectedColor.value = applyHSVFactors(extractedColor) + + // notify color changes to the listeners. + if (fromUser && debounceDuration != 0L) { + notifyColorChangedWithDebounce(fromUser) + } else { notifyColorChanged(fromUser) + } } - - /** Combine the brightness value to the selected pure color. */ - internal fun setBrightness(brightness: Float, fromUser: Boolean) { - this.brightness.value = brightness - val hsv = FloatArray(3) - android.graphics.Color.colorToHSV(pureSelectedColor.value.toArgb(), hsv) - hsv[2] = brightness - _selectedColor.value = - Color(android.graphics.Color.HSVToColor((alpha.value * 255).toInt(), hsv)) - if (fromUser && debounceDuration != 0L) { - notifyColorChangedWithDebounce(fromUser) - } else { - notifyColorChanged(fromUser) - } + } + + /** + * Select center point of the palette. + * + * @param fromUser Represents this event is triggered by user or not. + */ + public fun selectCenter(fromUser: Boolean) { + val size = canvasSize.value + selectByCoordinate(size.width * 0.5f, size.height * 0.5f, fromUser) + } + + /** Notify color changes to the color picker and other subcomponents. */ + private fun notifyColorChanged(fromUser: Boolean) { + val color = _selectedColor.value + colorChangedTick.value = ColorEnvelope(color, color.hexCode, fromUser) + } + + /** Notify color changes to the color picker and other subcomponents with debounce duration. */ + private fun notifyColorChangedWithDebounce(fromUser: Boolean) { + val runnable = { notifyColorChanged(fromUser) } + debounceHandler.removeCallbacksAndMessages(null) + debounceHandler.postDelayed(runnable, debounceDuration) + } + + /** Combine the alpha value to the selected pure color. */ + internal fun setAlpha(alpha: Float, fromUser: Boolean) { + this.alpha.value = alpha + _selectedColor.value = selectedColor.value.copy(alpha = alpha) + notifyColorChanged(fromUser) + } + + /** Combine the brightness value to the selected pure color. */ + internal fun setBrightness(brightness: Float, fromUser: Boolean) { + this.brightness.value = brightness + val hsv = FloatArray(3) + android.graphics.Color.colorToHSV(pureSelectedColor.value.toArgb(), hsv) + hsv[2] = brightness + _selectedColor.value = + Color(android.graphics.Color.HSVToColor((alpha.value * 255).toInt(), hsv)) + if (fromUser && debounceDuration != 0L) { + notifyColorChangedWithDebounce(fromUser) + } else { + notifyColorChanged(fromUser) } - - /** Return a [Color] that is applied with HSV color factors to the [color]. */ - private fun applyHSVFactors(color: Color): Color { - val hsv = FloatArray(3) - android.graphics.Color.colorToHSV(color.toArgb(), hsv) - if (isAttachedBrightnessSlider) { - hsv[2] = brightness.value - } - return if (isAttachedAlphaSlider) { - Color(android.graphics.Color.HSVToColor((alpha.value * 255).toInt(), hsv)) - } else { - Color(android.graphics.Color.HSVToColor(hsv)) - } + } + + /** Return a [Color] that is applied with HSV color factors to the [color]. */ + private fun applyHSVFactors(color: Color): Color { + val hsv = FloatArray(3) + android.graphics.Color.colorToHSV(color.toArgb(), hsv) + if (isAttachedBrightnessSlider) { + hsv[2] = brightness.value } - - /** - * Extract a pixel color from the [paletteBitmap]. - * - * @param x x-coordinate to extract a pixel color. - * @param y y-coordinate to extract a pixel color. - * - * @return An extracted [Color] from the desired coordinates. - * if fail to extract a pixel value, it will returns [Color.Transparent]. - */ - internal fun extractPixelColor(x: Float, y: Float): Color { - val invertMatrix = Matrix() - imageBitmapMatrix.value.invert(invertMatrix) - - val mappedPoints = floatArrayOf(x, y) - invertMatrix.mapPoints(mappedPoints) - - val palette = paletteBitmap - if (palette != null && - mappedPoints[0] >= 0 && - mappedPoints[1] >= 0 && - mappedPoints[0] < palette.width && - mappedPoints[1] < palette.height - ) { - val scaleX = mappedPoints[0] / palette.width - val x1 = scaleX * palette.width - val scaleY = mappedPoints[1] / palette.height - val y1 = scaleY * palette.height - val pixelColor = palette.asAndroidBitmap().getPixel(x1.toInt(), y1.toInt()) - return Color(pixelColor) - } - return Color.Transparent + return if (isAttachedAlphaSlider) { + Color(android.graphics.Color.HSVToColor((alpha.value * 255).toInt(), hsv)) + } else { + Color(android.graphics.Color.HSVToColor(hsv)) } - - private fun extractPixelHsvColor(x: Float, y: Float): Color { - val invertMatrix = Matrix() - imageBitmapMatrix.value.invert(invertMatrix) - - val mappedPoints = floatArrayOf(x, y) - invertMatrix.mapPoints(mappedPoints) - - val palette = paletteBitmap - if (palette != null && - mappedPoints[0] >= 0 && - mappedPoints[1] >= 0 && - mappedPoints[0] < palette.width && - mappedPoints[1] < palette.height - ) { - val x2 = x - palette.width * 0.5f - val y2 = y - palette.height * 0.5f - val size = canvasSize.value - val r = sqrt((x2 * x2 + y2 * y2).toDouble()) - val radius: Float = size.width.coerceAtMost(size.height) * 0.5f - val hsv = floatArrayOf(0f, 0f, 1f) - ( - ( - atan2( - y2.toDouble(), - -x2.toDouble(), - ) / Math.PI * 180f - ).toFloat() + 180 - ).also { hsv[0] = it } - hsv[1] = 0f.coerceAtLeast(1f.coerceAtMost((r / radius).toFloat())) - return Color(android.graphics.Color.HSVToColor(hsv)) - } - return Color.Transparent + } + + /** + * Extract a pixel color from the [paletteBitmap]. + * + * @param x x-coordinate to extract a pixel color. + * @param y y-coordinate to extract a pixel color. + * + * @return An extracted [Color] from the desired coordinates. + * if fail to extract a pixel value, it will returns [Color.Transparent]. + */ + internal fun extractPixelColor(x: Float, y: Float): Color { + val invertMatrix = Matrix() + imageBitmapMatrix.value.invert(invertMatrix) + + val mappedPoints = floatArrayOf(x, y) + invertMatrix.mapPoints(mappedPoints) + + val palette = paletteBitmap + if (palette != null && + mappedPoints[0] >= 0 && + mappedPoints[1] >= 0 && + mappedPoints[0] < palette.width && + mappedPoints[1] < palette.height + ) { + val scaleX = mappedPoints[0] / palette.width + val x1 = scaleX * palette.width + val scaleY = mappedPoints[1] / palette.height + val y1 = scaleY * palette.height + val pixelColor = palette.asAndroidBitmap().getPixel(x1.toInt(), y1.toInt()) + return Color(pixelColor) } - - internal fun releaseBitmap() { - paletteBitmap?.asAndroidBitmap()?.recycle() - wheelBitmap?.asAndroidBitmap()?.recycle() - paletteBitmap = null - wheelBitmap = null + return Color.Transparent + } + + private fun extractPixelHsvColor(x: Float, y: Float): Color { + val invertMatrix = Matrix() + imageBitmapMatrix.value.invert(invertMatrix) + + val mappedPoints = floatArrayOf(x, y) + invertMatrix.mapPoints(mappedPoints) + + val palette = paletteBitmap + if (palette != null && + mappedPoints[0] >= 0 && + mappedPoints[1] >= 0 && + mappedPoints[0] < palette.width && + mappedPoints[1] < palette.height + ) { + val x2 = x - palette.width * 0.5f + val y2 = y - palette.height * 0.5f + val size = canvasSize.value + val r = sqrt((x2 * x2 + y2 * y2).toDouble()) + val radius: Float = size.width.coerceAtMost(size.height) * 0.5f + val hsv = floatArrayOf(0f, 0f, 1f) + ( + ( + atan2( + y2.toDouble(), + -x2.toDouble(), + ) / Math.PI * 180f + ).toFloat() + 180 + ).also { hsv[0] = it } + hsv[1] = 0f.coerceAtLeast(1f.coerceAtMost((r / radius).toFloat())) + return Color(android.graphics.Color.HSVToColor(hsv)) } + return Color.Transparent + } + + internal fun releaseBitmap() { + paletteBitmap?.asAndroidBitmap()?.recycle() + wheelBitmap?.asAndroidBitmap()?.recycle() + paletteBitmap = null + wheelBitmap = null + } } diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/DrawScopeExtensions.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/DrawScopeExtensions.kt index 6c6029c..6ea328b 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/DrawScopeExtensions.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/DrawScopeExtensions.kt @@ -26,17 +26,17 @@ private const val SELECTOR_RADIUS: Float = 50f private const val BORDER_WIDTH: Float = 10f public fun DrawScope.drawColorIndicator(pos: PointF, color: Color) { - drawCircle(color, SELECTOR_RADIUS, Offset(pos.x, pos.y)) - drawCircle( - Color.White, - SELECTOR_RADIUS - (BORDER_WIDTH / 2), - Offset(pos.x, pos.y), - style = Stroke(width = BORDER_WIDTH), - ) - drawCircle( - Color.LightGray, - SELECTOR_RADIUS, - Offset(pos.x, pos.y), - style = Stroke(width = 1f), - ) + drawCircle(color, SELECTOR_RADIUS, Offset(pos.x, pos.y)) + drawCircle( + Color.White, + SELECTOR_RADIUS - (BORDER_WIDTH / 2), + Offset(pos.x, pos.y), + style = Stroke(width = BORDER_WIDTH), + ) + drawCircle( + Color.LightGray, + SELECTOR_RADIUS, + Offset(pos.x, pos.y), + style = Stroke(width = 1f), + ) } diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/HsvBitmapDrawable.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/HsvBitmapDrawable.kt index 0f903d5..cb0c213 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/HsvBitmapDrawable.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/HsvBitmapDrawable.kt @@ -36,63 +36,63 @@ import kotlin.math.min * @param bitmap [Bitmap] to draw on the canvas. */ internal class HsvBitmapDrawable constructor( - resources: Resources, - bitmap: Bitmap, + resources: Resources, + bitmap: Bitmap, ) : BitmapDrawable(resources, bitmap) { - private val huePaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) - private val saturationPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + private val huePaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + private val saturationPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) - override fun draw(canvas: Canvas) { - val width = bounds.width() - val height = bounds.height() - val centerX = width * 0.5f - val centerY = height * 0.5f - val radius = min(width, height) * 0.5f + override fun draw(canvas: Canvas) { + val width = bounds.width() + val height = bounds.height() + val centerX = width * 0.5f + val centerY = height * 0.5f + val radius = min(width, height) * 0.5f - val sweepShader = SweepGradient( - centerX, - centerY, - intArrayOf( - Color.RED, - Color.MAGENTA, - Color.BLUE, - Color.CYAN, - Color.GREEN, - Color.YELLOW, - Color.RED, - ), - floatArrayOf(0.000f, 0.166f, 0.333f, 0.499f, 0.666f, 0.833f, 0.999f), - ) - huePaint.shader = sweepShader + val sweepShader = SweepGradient( + centerX, + centerY, + intArrayOf( + Color.RED, + Color.MAGENTA, + Color.BLUE, + Color.CYAN, + Color.GREEN, + Color.YELLOW, + Color.RED, + ), + floatArrayOf(0.000f, 0.166f, 0.333f, 0.499f, 0.666f, 0.833f, 0.999f), + ) + huePaint.shader = sweepShader - val saturationShader = RadialGradient( - centerX, - centerY, - radius, - Color.WHITE, - 0x00FFFFFF, - Shader.TileMode.CLAMP, - ) - saturationPaint.shader = saturationShader + val saturationShader = RadialGradient( + centerX, + centerY, + radius, + Color.WHITE, + 0x00FFFFFF, + Shader.TileMode.CLAMP, + ) + saturationPaint.shader = saturationShader - canvas.drawCircle(centerX, centerY, radius, huePaint) - canvas.drawCircle(centerX, centerY, radius, saturationPaint) - } + canvas.drawCircle(centerX, centerY, radius, huePaint) + canvas.drawCircle(centerX, centerY, radius, saturationPaint) + } - override fun setAlpha(alpha: Int) { - huePaint.alpha = alpha - } + override fun setAlpha(alpha: Int) { + huePaint.alpha = alpha + } - override fun setColorFilter(colorFilter: ColorFilter?) { - huePaint.colorFilter = colorFilter - } + override fun setColorFilter(colorFilter: ColorFilter?) { + huePaint.colorFilter = colorFilter + } - @Deprecated( - message = "This method will be deprecated on the future Android SDK", - replaceWith = ReplaceWith(expression = "getOpacity"), - ) - override fun getOpacity(): Int { - return PixelFormat.OPAQUE - } + @Deprecated( + message = "This method will be deprecated on the future Android SDK", + replaceWith = ReplaceWith(expression = "getOpacity"), + ) + override fun getOpacity(): Int { + return PixelFormat.OPAQUE + } } diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/HsvColorPicker.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/HsvColorPicker.kt index e2ef9a5..175ebb7 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/HsvColorPicker.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/HsvColorPicker.kt @@ -62,143 +62,143 @@ import kotlin.math.sin */ @Composable public fun HsvColorPicker( - modifier: Modifier, - controller: ColorPickerController, - wheelImageBitmap: ImageBitmap? = null, - drawOnPosSelected: (DrawScope.() -> Unit)? = null, - drawDefaultWheelIndicator: Boolean = wheelImageBitmap == null && drawOnPosSelected == null, - onColorChanged: ((colorEnvelope: ColorEnvelope) -> Unit)? = null, - initialColor: Color? = null, + modifier: Modifier, + controller: ColorPickerController, + wheelImageBitmap: ImageBitmap? = null, + drawOnPosSelected: (DrawScope.() -> Unit)? = null, + drawDefaultWheelIndicator: Boolean = wheelImageBitmap == null && drawOnPosSelected == null, + onColorChanged: ((colorEnvelope: ColorEnvelope) -> Unit)? = null, + initialColor: Color? = null, ) { - var isInitialized by remember { mutableStateOf(false) } - val context = LocalContext.current - var hsvBitmapDrawable: HsvBitmapDrawable? = null - var bitmap: ImageBitmap? = null - val coroutineScope = rememberCoroutineScope() - DisposableEffect(key1 = controller) { - coroutineScope.launch(Dispatchers.Main) { - controller.isHsvColorPalette = true - bitmap?.let { controller.setPaletteImageBitmap(it) } - controller.setWheelImageBitmap(wheelImageBitmap) - controller.colorChangedTick.mapNotNull { it }.collect { - onColorChanged?.invoke(it) - } - } + var isInitialized by remember { mutableStateOf(false) } + val context = LocalContext.current + var hsvBitmapDrawable: HsvBitmapDrawable? = null + var bitmap: ImageBitmap? = null + val coroutineScope = rememberCoroutineScope() + DisposableEffect(key1 = controller) { + coroutineScope.launch(Dispatchers.Main) { + controller.isHsvColorPalette = true + bitmap?.let { controller.setPaletteImageBitmap(it) } + controller.setWheelImageBitmap(wheelImageBitmap) + controller.colorChangedTick.mapNotNull { it }.collect { + onColorChanged?.invoke(it) + } + } - onDispose { - controller.releaseBitmap() - } + onDispose { + controller.releaseBitmap() } + } - Canvas( - modifier = modifier - .fillMaxSize() - .onSizeChanged { newSize -> - val size = - newSize.takeIf { it.width != 0 && it.height != 0 } ?: return@onSizeChanged - controller.canvasSize.value = size - bitmap - ?.asAndroidBitmap() - ?.recycle() - bitmap = ImageBitmap(size.width, size.height, ImageBitmapConfig.Argb8888).also { - hsvBitmapDrawable = - HsvBitmapDrawable(context.resources, it.asAndroidBitmap()).apply { - setBounds( - 0, - 0, - size.width, - size.height, - ) - } + Canvas( + modifier = modifier + .fillMaxSize() + .onSizeChanged { newSize -> + val size = + newSize.takeIf { it.width != 0 && it.height != 0 } ?: return@onSizeChanged + controller.canvasSize.value = size + bitmap + ?.asAndroidBitmap() + ?.recycle() + bitmap = ImageBitmap(size.width, size.height, ImageBitmapConfig.Argb8888).also { + hsvBitmapDrawable = + HsvBitmapDrawable(context.resources, it.asAndroidBitmap()).apply { + setBounds( + 0, + 0, + size.width, + size.height, + ) + } - var dx = 0f - var dy = 0f - val scale: Float - val shaderMatrix = Matrix() - val mDrawableRect = RectF(0f, 0f, size.width.toFloat(), size.height.toFloat()) - val bitmapWidth: Int = it.asAndroidBitmap().width - val bitmapHeight: Int = it.asAndroidBitmap().height + var dx = 0f + var dy = 0f + val scale: Float + val shaderMatrix = Matrix() + val mDrawableRect = RectF(0f, 0f, size.width.toFloat(), size.height.toFloat()) + val bitmapWidth: Int = it.asAndroidBitmap().width + val bitmapHeight: Int = it.asAndroidBitmap().height - if (bitmapWidth * mDrawableRect.height() > - mDrawableRect.width() * bitmapHeight - ) { - scale = mDrawableRect.height() / bitmapHeight.toFloat() - dx = (mDrawableRect.width() - bitmapWidth * scale) * 0.5f - } else { - scale = mDrawableRect.width() / bitmapWidth.toFloat() - dy = (mDrawableRect.height() - bitmapHeight * scale) * 0.5f - } - // resize the matrix to scale by sx and sy. - shaderMatrix.setScale(scale, scale) + if (bitmapWidth * mDrawableRect.height() > + mDrawableRect.width() * bitmapHeight + ) { + scale = mDrawableRect.height() / bitmapHeight.toFloat() + dx = (mDrawableRect.width() - bitmapWidth * scale) * 0.5f + } else { + scale = mDrawableRect.width() / bitmapWidth.toFloat() + dy = (mDrawableRect.height() - bitmapHeight * scale) * 0.5f + } + // resize the matrix to scale by sx and sy. + shaderMatrix.setScale(scale, scale) - // post translate the matrix with the specified translation. - shaderMatrix.postTranslate( - (dx + 0.5f) + mDrawableRect.left, - (dy + 0.5f) + mDrawableRect.top, - ) + // post translate the matrix with the specified translation. + shaderMatrix.postTranslate( + (dx + 0.5f) + mDrawableRect.left, + (dy + 0.5f) + mDrawableRect.top, + ) - // set the shader matrix to the controller. - controller.imageBitmapMatrix.value = shaderMatrix - } - } - .pointerInput(Unit) { - detectTapGestures { offset -> - controller.selectByCoordinate(offset.x, offset.y, true) - } - } - .pointerInput(Unit) { - detectDragGestures { change, _ -> - controller.selectByCoordinate(change.position.x, change.position.y, true) - } - }, - ) { - drawIntoCanvas { canvas -> - // draw hsv bitmap on the canvas. - hsvBitmapDrawable?.draw(canvas.nativeCanvas) + // set the shader matrix to the controller. + controller.imageBitmapMatrix.value = shaderMatrix + } + } + .pointerInput(Unit) { + detectTapGestures { offset -> + controller.selectByCoordinate(offset.x, offset.y, true) + } + } + .pointerInput(Unit) { + detectDragGestures { change, _ -> + controller.selectByCoordinate(change.position.x, change.position.y, true) + } + }, + ) { + drawIntoCanvas { canvas -> + // draw hsv bitmap on the canvas. + hsvBitmapDrawable?.draw(canvas.nativeCanvas) - // draw wheel bitmap on the canvas. - val point = controller.selectedPoint.value - val wheelBitmap = controller.wheelBitmap - if (wheelBitmap != null) { - canvas.drawImage( - wheelBitmap, - Offset(point.x - wheelBitmap.width / 2, point.y - wheelBitmap.height / 2), - Paint(), - ) - } + // draw wheel bitmap on the canvas. + val point = controller.selectedPoint.value + val wheelBitmap = controller.wheelBitmap + if (wheelBitmap != null) { + canvas.drawImage( + wheelBitmap, + Offset(point.x - wheelBitmap.width / 2, point.y - wheelBitmap.height / 2), + Paint(), + ) + } - if (drawDefaultWheelIndicator) { - canvas.drawCircle( - Offset(point.x, point.y), - controller.wheelRadius.toPx(), - controller.wheelPaint, - ) - } + if (drawDefaultWheelIndicator) { + canvas.drawCircle( + Offset(point.x, point.y), + controller.wheelRadius.toPx(), + controller.wheelPaint, + ) + } - if (drawOnPosSelected != null) { - this.drawOnPosSelected() - } + if (drawOnPosSelected != null) { + this.drawOnPosSelected() + } - val palette = controller.paletteBitmap - if (palette != null && initialColor != null && !isInitialized) { - val pickerRadius: Float = palette.width.coerceAtMost(palette.height) * 0.5f - if (pickerRadius > 0) { - isInitialized = true - val hsv = FloatArray(3) - android.graphics.Color.RGBToHSV( - (initialColor.red * 255).toInt(), - (initialColor.green * 255).toInt(), - (initialColor.blue * 255).toInt(), - hsv, - ) - val angle = (Math.PI / 180f) * hsv[0] * (-1) - val saturationVector = pickerRadius * hsv[1] - val x = saturationVector * cos(angle) + center.x - val y = saturationVector * sin(angle) + center.y - controller.selectByCoordinate(x.toFloat(), y.toFloat(), false) - } - } + val palette = controller.paletteBitmap + if (palette != null && initialColor != null && !isInitialized) { + val pickerRadius: Float = palette.width.coerceAtMost(palette.height) * 0.5f + if (pickerRadius > 0) { + isInitialized = true + val hsv = FloatArray(3) + android.graphics.Color.RGBToHSV( + (initialColor.red * 255).toInt(), + (initialColor.green * 255).toInt(), + (initialColor.blue * 255).toInt(), + hsv, + ) + val angle = (Math.PI / 180f) * hsv[0] * (-1) + val saturationVector = pickerRadius * hsv[1] + val x = saturationVector * cos(angle) + center.x + val y = saturationVector * sin(angle) + center.y + controller.selectByCoordinate(x.toFloat(), y.toFloat(), false) } - controller.reviseTick.value + } } + controller.reviseTick.value + } } diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ImageColorPicker.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ImageColorPicker.kt index 835fce7..82fc881 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ImageColorPicker.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/ImageColorPicker.kt @@ -56,130 +56,130 @@ import kotlinx.coroutines.launch */ @Composable public fun ImageColorPicker( - modifier: Modifier, - controller: ColorPickerController, - paletteImageBitmap: ImageBitmap, - wheelImageBitmap: ImageBitmap? = null, - drawOnPosSelected: (DrawScope.() -> Unit)? = null, - drawDefaultWheelIndicator: Boolean = wheelImageBitmap == null && drawOnPosSelected == null, - paletteContentScale: PaletteContentScale = PaletteContentScale.FIT, - onColorChanged: ((colorEnvelope: ColorEnvelope) -> Unit)? = null, + modifier: Modifier, + controller: ColorPickerController, + paletteImageBitmap: ImageBitmap, + wheelImageBitmap: ImageBitmap? = null, + drawOnPosSelected: (DrawScope.() -> Unit)? = null, + drawDefaultWheelIndicator: Boolean = wheelImageBitmap == null && drawOnPosSelected == null, + paletteContentScale: PaletteContentScale = PaletteContentScale.FIT, + onColorChanged: ((colorEnvelope: ColorEnvelope) -> Unit)? = null, ) { - val coroutineScope = rememberCoroutineScope() - DisposableEffect(key1 = controller) { - coroutineScope.launch(Dispatchers.Main) { - with(controller) { - setPaletteContentScale(paletteContentScale) - setPaletteImageBitmap(paletteImageBitmap) - setWheelImageBitmap(wheelImageBitmap) - colorChangedTick.mapNotNull { it }.collect { - onColorChanged?.invoke(it) - } - } + val coroutineScope = rememberCoroutineScope() + DisposableEffect(key1 = controller) { + coroutineScope.launch(Dispatchers.Main) { + with(controller) { + setPaletteContentScale(paletteContentScale) + setPaletteImageBitmap(paletteImageBitmap) + setWheelImageBitmap(wheelImageBitmap) + colorChangedTick.mapNotNull { it }.collect { + onColorChanged?.invoke(it) } + } + } - onDispose { - controller.releaseBitmap() - } + onDispose { + controller.releaseBitmap() } + } - Canvas( - modifier = modifier - .onSizeChanged { size -> - if (size.width != 0 && size.height != 0) { - controller.canvasSize.value = size - } - } - .pointerInteropFilter { event -> - when (event.action) { - MotionEvent.ACTION_DOWN, - MotionEvent.ACTION_MOVE, - MotionEvent.ACTION_UP, - -> { - controller.selectByCoordinate(event.x, event.y, true) - true - } - else -> false - } - }, - ) { - drawIntoCanvas { canvas -> - // draw image bitmap on the canvas. - controller.paletteBitmap?.let { imageBitmap -> - var dx = 0f - var dy = 0f - val scale: Float - val shaderMatrix = Matrix() - val shader = ImageShader(imageBitmap, TileMode.Clamp) - val brush = ShaderBrush(shader) - val paint = paintPool.acquire() ?: Paint() - paint.asFrameworkPaint().apply { - isAntiAlias = true - isDither = true - isFilterBitmap = true - } + Canvas( + modifier = modifier + .onSizeChanged { size -> + if (size.width != 0 && size.height != 0) { + controller.canvasSize.value = size + } + } + .pointerInteropFilter { event -> + when (event.action) { + MotionEvent.ACTION_DOWN, + MotionEvent.ACTION_MOVE, + MotionEvent.ACTION_UP, + -> { + controller.selectByCoordinate(event.x, event.y, true) + true + } + else -> false + } + }, + ) { + drawIntoCanvas { canvas -> + // draw image bitmap on the canvas. + controller.paletteBitmap?.let { imageBitmap -> + var dx = 0f + var dy = 0f + val scale: Float + val shaderMatrix = Matrix() + val shader = ImageShader(imageBitmap, TileMode.Clamp) + val brush = ShaderBrush(shader) + val paint = paintPool.acquire() ?: Paint() + paint.asFrameworkPaint().apply { + isAntiAlias = true + isDither = true + isFilterBitmap = true + } - // cache the paint in the internal stack. - canvas.saveLayer(size.toRect(), paint) + // cache the paint in the internal stack. + canvas.saveLayer(size.toRect(), paint) - val mDrawableRect = RectF(0f, 0f, size.width, size.height) - val bitmapWidth: Int = imageBitmap.asAndroidBitmap().width - val bitmapHeight: Int = imageBitmap.asAndroidBitmap().height + val mDrawableRect = RectF(0f, 0f, size.width, size.height) + val bitmapWidth: Int = imageBitmap.asAndroidBitmap().width + val bitmapHeight: Int = imageBitmap.asAndroidBitmap().height - if (bitmapWidth * mDrawableRect.height() > mDrawableRect.width() * bitmapHeight) { - scale = mDrawableRect.height() / bitmapHeight.toFloat() - dx = (mDrawableRect.width() - bitmapWidth * scale) * 0.5f - } else { - scale = mDrawableRect.width() / bitmapWidth.toFloat() - dy = (mDrawableRect.height() - bitmapHeight * scale) * 0.5f - } + if (bitmapWidth * mDrawableRect.height() > mDrawableRect.width() * bitmapHeight) { + scale = mDrawableRect.height() / bitmapHeight.toFloat() + dx = (mDrawableRect.width() - bitmapWidth * scale) * 0.5f + } else { + scale = mDrawableRect.width() / bitmapWidth.toFloat() + dy = (mDrawableRect.height() - bitmapHeight * scale) * 0.5f + } - // resize the matrix to scale by sx and sy. - shaderMatrix.setScale(scale, scale) + // resize the matrix to scale by sx and sy. + shaderMatrix.setScale(scale, scale) - // post translate the matrix with the specified translation. - shaderMatrix.postTranslate( - (dx + 0.5f) + mDrawableRect.left, - (dy + 0.5f) + mDrawableRect.top, - ) - // apply the scaled matrix to the shader. - shader.setLocalMatrix(shaderMatrix) - // Set the shader matrix to the controller. - controller.imageBitmapMatrix.value = shaderMatrix - // draw an image bitmap as a rect. - drawRect(brush = brush, size = controller.canvasSize.value.toSize()) - // restore canvas. - canvas.restore() - // resets the paint and release to the pool. - paint.asFrameworkPaint().reset() - paintPool.release(paint) - } + // post translate the matrix with the specified translation. + shaderMatrix.postTranslate( + (dx + 0.5f) + mDrawableRect.left, + (dy + 0.5f) + mDrawableRect.top, + ) + // apply the scaled matrix to the shader. + shader.setLocalMatrix(shaderMatrix) + // Set the shader matrix to the controller. + controller.imageBitmapMatrix.value = shaderMatrix + // draw an image bitmap as a rect. + drawRect(brush = brush, size = controller.canvasSize.value.toSize()) + // restore canvas. + canvas.restore() + // resets the paint and release to the pool. + paint.asFrameworkPaint().reset() + paintPool.release(paint) + } - // draw wheel bitmap on the canvas. - val point = controller.selectedPoint.value - val wheelBitmap = controller.wheelBitmap - if (wheelBitmap != null) { - canvas.drawImage( - wheelBitmap, - Offset(point.x - wheelBitmap.width / 2, point.y - wheelBitmap.height / 2), - Paint(), - ) - } + // draw wheel bitmap on the canvas. + val point = controller.selectedPoint.value + val wheelBitmap = controller.wheelBitmap + if (wheelBitmap != null) { + canvas.drawImage( + wheelBitmap, + Offset(point.x - wheelBitmap.width / 2, point.y - wheelBitmap.height / 2), + Paint(), + ) + } - if (drawDefaultWheelIndicator) { - canvas.drawCircle( - Offset(point.x, point.y), - controller.wheelRadius.toPx(), - controller.wheelPaint, - ) - } + if (drawDefaultWheelIndicator) { + canvas.drawCircle( + Offset(point.x, point.y), + controller.wheelRadius.toPx(), + controller.wheelPaint, + ) + } - if (drawOnPosSelected != null) { - this.drawOnPosSelected() - } - } - controller.reviseTick.value + if (drawOnPosSelected != null) { + this.drawOnPosSelected() + } } + controller.reviseTick.value + } } /** paint pool which caching and reusing [Paint] instances. */ diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/PaletteContentScale.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/PaletteContentScale.kt index 284da2e..9efca58 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/PaletteContentScale.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/PaletteContentScale.kt @@ -18,24 +18,24 @@ package com.github.skydoves.colorpicker.compose /** Represents a rule to apply to scale a source rectangle to be inscribed into a destination. */ public enum class PaletteContentScale { - /** - * Scale the source with maintaining the source's aspect ratio - * so that both dimensions (width and height) of the source will be equal to or less than the - * corresponding dimension of the target size. - */ - FIT, + /** + * Scale the source with maintaining the source's aspect ratio + * so that both dimensions (width and height) of the source will be equal to or less than the + * corresponding dimension of the target size. + */ + FIT, - /** - * Crop ths source the corresponding dimension of the target size. - * so that if the dimensions (width and height) source is bigger than the target size, - * it will be cut off from the center. - */ - CROP, + /** + * Crop ths source the corresponding dimension of the target size. + * so that if the dimensions (width and height) source is bigger than the target size, + * it will be cut off from the center. + */ + CROP, - /** - * Scale the source with maintaining the source's aspect ratio - * so that if both dimensions (width and height) of the source is smaller than the target size, - * it will not be scaled. - */ + /** + * Scale the source with maintaining the source's aspect ratio + * so that if both dimensions (width and height) of the source is smaller than the target size, + * it will not be scaled. + */ // INSIDE, } diff --git a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/PointMapper.kt b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/PointMapper.kt index 2e3cdf3..634386e 100644 --- a/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/PointMapper.kt +++ b/colorpicker-compose/src/main/kotlin/com/github/skydoves/colorpicker/compose/PointMapper.kt @@ -26,56 +26,56 @@ import kotlin.math.sqrt */ internal object PointMapper { - internal fun getColorPoint(controller: ColorPickerController, point: PointF): PointF { - val size = controller.canvasSize.value - val center = PointF(size.width / 2f, size.height / 2f) - return if (controller.isHsvColorPalette) { - getHuePoint(controller, point) - } else { - approximatedPoint(controller, point, center) - } + internal fun getColorPoint(controller: ColorPickerController, point: PointF): PointF { + val size = controller.canvasSize.value + val center = PointF(size.width / 2f, size.height / 2f) + return if (controller.isHsvColorPalette) { + getHuePoint(controller, point) + } else { + approximatedPoint(controller, point, center) } + } - private fun approximatedPoint( - controller: ColorPickerController, - start: PointF, - end: PointF, - ): PointF { - if (getDistance(start, end) <= 3) return end - val center: PointF = getCenterPoint(start, end) - val color: Color = controller.extractPixelColor(center.x, center.y) - return if (color == Color.Transparent) { - approximatedPoint(controller, center, end) - } else { - approximatedPoint(controller, start, center) - } + private fun approximatedPoint( + controller: ColorPickerController, + start: PointF, + end: PointF, + ): PointF { + if (getDistance(start, end) <= 3) return end + val center: PointF = getCenterPoint(start, end) + val color: Color = controller.extractPixelColor(center.x, center.y) + return if (color == Color.Transparent) { + approximatedPoint(controller, center, end) + } else { + approximatedPoint(controller, start, center) } + } - private fun getHuePoint(controller: ColorPickerController, point: PointF): PointF { - val size = controller.canvasSize.value - val centerX: Float = size.width * 0.5f - val centerY: Float = size.height * 0.5f - var x = point.x - centerX - var y = point.y - centerY - val radius = centerX.coerceAtMost(centerY) - val r = sqrt((x * x + y * y).toDouble()) - if (r > radius) { - x *= (radius / r).toFloat() - y *= (radius / r).toFloat() - } - return PointF(x + centerX, y + centerY) + private fun getHuePoint(controller: ColorPickerController, point: PointF): PointF { + val size = controller.canvasSize.value + val centerX: Float = size.width * 0.5f + val centerY: Float = size.height * 0.5f + var x = point.x - centerX + var y = point.y - centerY + val radius = centerX.coerceAtMost(centerY) + val r = sqrt((x * x + y * y).toDouble()) + if (r > radius) { + x *= (radius / r).toFloat() + y *= (radius / r).toFloat() } + return PointF(x + centerX, y + centerY) + } - private fun getCenterPoint(start: PointF, end: PointF): PointF { - return PointF((end.x + start.x) / 2, (end.y + start.y) / 2) - } + private fun getCenterPoint(start: PointF, end: PointF): PointF { + return PointF((end.x + start.x) / 2, (end.y + start.y) / 2) + } - private fun getDistance(start: PointF, end: PointF): Int { - return sqrt( - ( - abs(end.x - start.x) * abs(end.x - start.x) + - abs(end.y - start.y) * abs(end.y - start.y) - ).toDouble(), - ).toInt() - } + private fun getDistance(start: PointF, end: PointF): Int { + return sqrt( + ( + abs(end.x - start.x) * abs(end.x - start.x) + + abs(end.y - start.y) * abs(end.y - start.y) + ).toDouble(), + ).toInt() + } } diff --git a/spotless.gradle b/spotless.gradle index 90aca4b..6a05793 100644 --- a/spotless.gradle +++ b/spotless.gradle @@ -3,7 +3,7 @@ apply plugin: "com.diffplug.spotless" spotless { kotlin { target "**/*.kt" - ktlint().setUseExperimental(true).editorConfigOverride(['indent_size': '4', 'continuation_indent_size': '4']) + ktlint().editorConfigOverride(['indent_size': '2', 'continuation_indent_size': '2']) licenseHeaderFile "$rootDir/spotless.license.kt" trimTrailingWhitespace() endWithNewline()