diff --git a/app/src/main/java/com/fibelatti/photowidget/configure/PhotoWidgetConfigureScreen.kt b/app/src/main/java/com/fibelatti/photowidget/configure/PhotoWidgetConfigureScreen.kt
index fd07de9..c88e3c2 100644
--- a/app/src/main/java/com/fibelatti/photowidget/configure/PhotoWidgetConfigureScreen.kt
+++ b/app/src/main/java/com/fibelatti/photowidget/configure/PhotoWidgetConfigureScreen.kt
@@ -215,28 +215,15 @@ private fun PhotoWidgetConfigureContent(
)
}
- val allPhotosCropped = remember(photos) { photos.all { it.isCropped } }
-
FilledTonalButton(
onClick = onAddToHomeClick,
modifier = Modifier
.fillMaxWidth()
.padding(start = 16.dp, top = 32.dp, end = 16.dp),
- enabled = allPhotosCropped,
) {
Text(text = stringResource(id = R.string.photo_widget_configure_add_to_home))
}
- AnimatedVisibility(visible = !allPhotosCropped) {
- Text(
- text = stringResource(id = R.string.photo_widget_configure_cropping_required),
- modifier = Modifier.padding(start = 72.dp, top = 8.dp, end = 72.dp),
- textAlign = TextAlign.Center,
- color = MaterialTheme.colorScheme.onSurfaceVariant,
- style = MaterialTheme.typography.labelSmall,
- )
- }
-
Spacer(modifier = Modifier.size(32.dp))
}
}
@@ -358,8 +345,6 @@ private fun PhotoPicker(
modifier = modifier.fillMaxWidth(),
verticalArrangement = Arrangement.spacedBy(8.dp),
) {
- val croppedPhotos = photos.count { it.isCropped }
-
Text(
text = stringResource(
id = if (photos.isEmpty()) {
@@ -367,8 +352,6 @@ private fun PhotoPicker(
} else {
R.string.photo_widget_configure_selected_photos
},
- croppedPhotos,
- photos.size,
),
modifier = Modifier.padding(horizontal = 16.dp),
style = MaterialTheme.typography.titleMedium,
@@ -426,24 +409,6 @@ private fun PhotoPicker(
role = Role.Image,
onClick = { onPhotoClick(photo) },
),
- badge = {
- if (!photo.isCropped) {
- Image(
- painter = painterResource(id = R.drawable.ic_crop),
- contentDescription = "",
- modifier = Modifier
- .padding(all = 8.dp)
- .background(
- color = MaterialTheme.colorScheme.errorContainer,
- shape = CircleShape,
- )
- .padding(all = 4.dp)
- .size(size = 12.dp)
- .align(Alignment.BottomEnd),
- colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.onErrorContainer),
- )
- }
- },
)
}
}
@@ -566,11 +531,11 @@ fun ShapedPhoto(
height = photoBitmap.height,
)
- photoBitmap.withPolygonalShape(shape).asImageBitmap()
+ photoBitmap.withPolygonalShape(roundedPolygon = shape).asImageBitmap()
}
} else {
remember(photo, aspectRatio) {
- photoBitmap.withRoundedCorners().asImageBitmap()
+ photoBitmap.withRoundedCorners(desiredAspectRatio = aspectRatio).asImageBitmap()
}
}
diff --git a/app/src/main/java/com/fibelatti/photowidget/configure/PhotoWidgetConfigureViewModel.kt b/app/src/main/java/com/fibelatti/photowidget/configure/PhotoWidgetConfigureViewModel.kt
index c8bdff9..9becc02 100644
--- a/app/src/main/java/com/fibelatti/photowidget/configure/PhotoWidgetConfigureViewModel.kt
+++ b/app/src/main/java/com/fibelatti/photowidget/configure/PhotoWidgetConfigureViewModel.kt
@@ -118,19 +118,13 @@ class PhotoWidgetConfigureViewModel @Inject constructor(
current.copy(
photos = current.photos.map { photo ->
if (photo.path == path) {
- photo.copy(
- isCropped = true,
- timestamp = System.currentTimeMillis(),
- )
+ photo.copy(timestamp = System.currentTimeMillis())
} else {
photo
}
},
selectedPhoto = if (current.selectedPhoto?.path == path) {
- current.selectedPhoto.copy(
- isCropped = true,
- timestamp = System.currentTimeMillis(),
- )
+ current.selectedPhoto.copy(timestamp = System.currentTimeMillis())
} else {
current.selectedPhoto
},
diff --git a/app/src/main/java/com/fibelatti/photowidget/model/LocalPhoto.kt b/app/src/main/java/com/fibelatti/photowidget/model/LocalPhoto.kt
index 2a0a1aa..d288e83 100644
--- a/app/src/main/java/com/fibelatti/photowidget/model/LocalPhoto.kt
+++ b/app/src/main/java/com/fibelatti/photowidget/model/LocalPhoto.kt
@@ -3,6 +3,5 @@ package com.fibelatti.photowidget.model
data class LocalPhoto(
val name: String,
val path: String,
- val isCropped: Boolean,
val timestamp: Long = System.currentTimeMillis(),
)
diff --git a/app/src/main/java/com/fibelatti/photowidget/model/PhotoWidgetAspectRatio.kt b/app/src/main/java/com/fibelatti/photowidget/model/PhotoWidgetAspectRatio.kt
index fd20cb9..1b8b1a4 100644
--- a/app/src/main/java/com/fibelatti/photowidget/model/PhotoWidgetAspectRatio.kt
+++ b/app/src/main/java/com/fibelatti/photowidget/model/PhotoWidgetAspectRatio.kt
@@ -2,6 +2,8 @@ package com.fibelatti.photowidget.model
import androidx.annotation.StringRes
import com.fibelatti.photowidget.R
+import kotlin.math.max
+import kotlin.math.min
enum class PhotoWidgetAspectRatio(
val x: Float,
@@ -26,5 +28,9 @@ enum class PhotoWidgetAspectRatio(
),
;
- val aspectRatio: Float get(): Float = x / y
+ val aspectRatio: Float
+ get() = x / y
+
+ val scale: Float
+ get() = min(x, y) / max(x, y)
}
diff --git a/app/src/main/java/com/fibelatti/photowidget/model/PhotoWidgetShapeBuilder.kt b/app/src/main/java/com/fibelatti/photowidget/model/PhotoWidgetShapeBuilder.kt
index 5dafe7f..5c232a5 100644
--- a/app/src/main/java/com/fibelatti/photowidget/model/PhotoWidgetShapeBuilder.kt
+++ b/app/src/main/java/com/fibelatti/photowidget/model/PhotoWidgetShapeBuilder.kt
@@ -139,7 +139,7 @@ object PhotoWidgetShapeBuilder {
}
}
- private fun calculateMatrix(bounds: RectF, width: Int, height: Int): Matrix {
+ fun calculateMatrix(bounds: RectF, width: Int, height: Int): Matrix {
val scale = calculateScale(bounds = bounds, width = width, height = height)
val scaledLeft = scale * bounds.left
val scaledTop = scale * bounds.top
diff --git a/app/src/main/java/com/fibelatti/photowidget/platform/BitmapKtx.kt b/app/src/main/java/com/fibelatti/photowidget/platform/BitmapKtx.kt
index b350169..e9f3cdb 100644
--- a/app/src/main/java/com/fibelatti/photowidget/platform/BitmapKtx.kt
+++ b/app/src/main/java/com/fibelatti/photowidget/platform/BitmapKtx.kt
@@ -2,6 +2,7 @@ package com.fibelatti.photowidget.platform
import android.graphics.Bitmap
import android.graphics.Canvas
+import android.graphics.Matrix
import android.graphics.Paint
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
@@ -9,33 +10,95 @@ import android.graphics.Rect
import androidx.core.graphics.toRectF
import androidx.graphics.shapes.RoundedPolygon
import androidx.graphics.shapes.drawPolygon
+import com.fibelatti.photowidget.model.PhotoWidgetAspectRatio
+import com.fibelatti.photowidget.model.PhotoWidgetShapeBuilder
+import kotlin.math.min
+import kotlin.math.roundToInt
fun Bitmap.withRoundedCorners(
+ desiredAspectRatio: PhotoWidgetAspectRatio,
radius: Float = 64f,
-): Bitmap = withTransformation { canvas, rect, paint ->
+): Bitmap = withTransformation(desiredAspectRatio = desiredAspectRatio) { canvas, rect, paint ->
canvas.drawRoundRect(rect.toRectF(), radius, radius, paint)
}
fun Bitmap.withPolygonalShape(
roundedPolygon: RoundedPolygon,
-): Bitmap = withTransformation { canvas, _, paint ->
- canvas.drawPolygon(polygon = roundedPolygon, paint = paint)
+): Bitmap = withTransformation(desiredAspectRatio = PhotoWidgetAspectRatio.SQUARE) { canvas, rect, paint ->
+ canvas.drawPolygon(
+ polygon = roundedPolygon.also {
+ it.transform(
+ matrix = PhotoWidgetShapeBuilder.calculateMatrix(
+ bounds = rect.toRectF(),
+ width = rect.width(),
+ height = rect.height(),
+ ),
+ )
+ },
+ paint = paint,
+ )
}
-private inline fun Bitmap.withTransformation(body: (Canvas, Rect, Paint) -> Unit): Bitmap {
- val output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
+private inline fun Bitmap.withTransformation(
+ desiredAspectRatio: PhotoWidgetAspectRatio,
+ body: (Canvas, Rect, Paint) -> Unit,
+): Bitmap {
+ val source = when (desiredAspectRatio) {
+ PhotoWidgetAspectRatio.SQUARE -> {
+ val size = min(height, width)
+
+ val top = (height - size) / 2
+ val left = (width - size) / 2
+
+ Rect(left, top, left + size, top + size)
+ }
+
+ PhotoWidgetAspectRatio.TALL -> {
+ val baseWidth = (height * PhotoWidgetAspectRatio.TALL.scale)
+
+ val scaledWidth = baseWidth.roundToInt().coerceAtMost(width)
+ val scaledHeight = if (baseWidth > width) {
+ (width / baseWidth.roundToInt()) * height
+ } else {
+ height
+ }
+
+ val top = (height - scaledHeight) / 2
+ val left = (width - scaledWidth) / 2
+
+ Rect(left, top, left + scaledWidth, top + scaledHeight)
+ }
+
+ PhotoWidgetAspectRatio.WIDE -> {
+ val baseHeight = (width * PhotoWidgetAspectRatio.WIDE.scale)
+
+ val scaledHeight = baseHeight.roundToInt().coerceAtMost(height)
+ val scaledWidth = if (baseHeight > height) {
+ (height / baseHeight.roundToInt()) * width
+ } else {
+ width
+ }
+
+ val top = (height - scaledHeight) / 2
+ val left = (width - scaledWidth) / 2
+
+ Rect(left, top, left + scaledWidth, top + scaledHeight)
+ }
+ }
+ val destination = Rect(0, 0, source.width(), source.height())
+
+ val output = Bitmap.createBitmap(source.width(), source.height(), Bitmap.Config.ARGB_8888)
val canvas = Canvas(output)
val paint = Paint().apply {
isAntiAlias = true
}
- val rect = Rect(0, 0, width, height)
canvas.drawARGB(0, 0, 0, 0)
- body(canvas, rect, paint)
+ body(canvas, if (PhotoWidgetAspectRatio.SQUARE == desiredAspectRatio) source else destination, paint)
paint.setXfermode(PorterDuffXfermode(PorterDuff.Mode.SRC_IN))
- canvas.drawBitmap(this, rect, rect, paint)
+ canvas.drawBitmap(this, source, destination, paint)
return output
}
diff --git a/app/src/main/java/com/fibelatti/photowidget/widget/PhotoWidgetProvider.kt b/app/src/main/java/com/fibelatti/photowidget/widget/PhotoWidgetProvider.kt
index c3ff4ca..de7ddc3 100644
--- a/app/src/main/java/com/fibelatti/photowidget/widget/PhotoWidgetProvider.kt
+++ b/app/src/main/java/com/fibelatti/photowidget/widget/PhotoWidgetProvider.kt
@@ -112,9 +112,9 @@ class PhotoWidgetProvider : AppWidgetProvider() {
height = bitmap.height,
)
- bitmap.withPolygonalShape(shape)
+ bitmap.withPolygonalShape(roundedPolygon = shape)
} else {
- bitmap.withRoundedCorners()
+ bitmap.withRoundedCorners(desiredAspectRatio = aspectRatio)
}
return RemoteViews(context.packageName, R.layout.photo_widget).apply {
diff --git a/app/src/main/java/com/fibelatti/photowidget/widget/PhotoWidgetStorage.kt b/app/src/main/java/com/fibelatti/photowidget/widget/PhotoWidgetStorage.kt
index a58c593..e949e67 100644
--- a/app/src/main/java/com/fibelatti/photowidget/widget/PhotoWidgetStorage.kt
+++ b/app/src/main/java/com/fibelatti/photowidget/widget/PhotoWidgetStorage.kt
@@ -87,7 +87,6 @@ class PhotoWidgetStorage @Inject constructor(@ApplicationContext context: Contex
return@withContext LocalPhoto(
name = newPhotoName,
path = croppedPhoto.path,
- isCropped = false,
)
}
@@ -100,7 +99,6 @@ class PhotoWidgetStorage @Inject constructor(@ApplicationContext context: Contex
LocalPhoto(
name = file,
path = "$dir/$file",
- isCropped = true,
)
}
}
diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml
index a8d89eb..eeb0a46 100644
--- a/app/src/main/res/values-pt/strings.xml
+++ b/app/src/main/res/values-pt/strings.xml
@@ -38,7 +38,7 @@
As alterações serão perdidas, voltar mesmo assim?
Escolha uma foto
- Fotos escolhidas (%1$d/%2$d recortadas)
+ Fotos escolhidas
Recortar
Remover
@@ -55,7 +55,6 @@
Forma
Adicionar à tela inicial
- Você deve recortar todas as fotos antes de adicionar este widget à sua tela inicial
Sim
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 805a6c6..a404d08 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -38,7 +38,7 @@
Any changes will be lost, go back anyway?
Select a photo
- Selected photos (%1$d/%2$d cropped)
+ Selected photos
Crop
Remove
@@ -55,7 +55,6 @@
Applied shape
Add to home screen
- You must crop all photos before adding this widget to your home screen
Yes