From b7607eebd9c76949eb8377397c7b09bf31367ffb Mon Sep 17 00:00:00 2001 From: xfy Date: Thu, 23 Jul 2026 15:02:11 +0800 Subject: [PATCH] =?UTF-8?q?fix(photo-editor):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E7=85=A7=E7=89=87=E6=97=8B=E8=BD=AC=E4=BA=8C=E6=AC=A1=E5=8F=A0?= =?UTF-8?q?=E5=8A=A0=E4=B8=8E=E9=BB=91=E8=BE=B9=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plus/rua/project/ui/PhotoEditorScreen.kt | 25 +++++++++++++------ .../plus/rua/project/RotationGeometryTest.kt | 7 ++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/core/src/main/kotlin/plus/rua/project/ui/PhotoEditorScreen.kt b/core/src/main/kotlin/plus/rua/project/ui/PhotoEditorScreen.kt index a110c38..6ffb187 100644 --- a/core/src/main/kotlin/plus/rua/project/ui/PhotoEditorScreen.kt +++ b/core/src/main/kotlin/plus/rua/project/ui/PhotoEditorScreen.kt @@ -79,6 +79,8 @@ import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.layout.layout +import androidx.compose.ui.unit.Constraints import androidx.compose.ui.platform.testTag import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTagsAsResourceId @@ -384,14 +386,23 @@ private fun EditableImage( val angle = displayRotation.value val offset = angle - state.rotationDegrees val scale = RotationGeometry.coverScale(offset, containerAspect) - val rotatedBmp = remember(state.rotationDegrees, state.sourceBitmap) { - state.rotatedBitmap - } Image( - bitmap = rotatedBmp.asImageBitmap(), + bitmap = state.sourceBitmap.asImageBitmap(), contentDescription = "编辑中的照片", modifier = Modifier - .fillMaxSize() + .layout { measurable, constraints -> + val isSwapped = (state.rotationDegrees % 180 != 0) + val targetWidth = if (isSwapped) constraints.maxHeight else constraints.maxWidth + val targetHeight = if (isSwapped) constraints.maxWidth else constraints.maxHeight + val placeable = measurable.measure( + Constraints.fixed(targetWidth, targetHeight) + ) + layout(constraints.maxWidth, constraints.maxHeight) { + val x = (constraints.maxWidth - targetWidth) / 2 + val y = (constraints.maxHeight - targetHeight) / 2 + placeable.placeRelative(x, y) + } + } .graphicsLayer { rotationZ = angle scaleX = scale @@ -410,7 +421,7 @@ private fun EditableImage( ) } }, - contentScale = ContentScale.Crop + contentScale = ContentScale.Fit ) if (mode == EditTab.CROP && state.cropEnabled) { @@ -644,7 +655,7 @@ private fun ToolPanel( border = BorderStroke(1.dp, MaterialTheme.colorScheme.outlineVariant) ) { Text( - text = "${state.rotationDegrees}°", + text = "${(state.rotationDegrees % 360 + 360) % 360}°", style = MaterialTheme.typography.labelMedium, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.primary, diff --git a/core/src/test/kotlin/plus/rua/project/RotationGeometryTest.kt b/core/src/test/kotlin/plus/rua/project/RotationGeometryTest.kt index 28afe69..5c06b54 100644 --- a/core/src/test/kotlin/plus/rua/project/RotationGeometryTest.kt +++ b/core/src/test/kotlin/plus/rua/project/RotationGeometryTest.kt @@ -31,6 +31,13 @@ class RotationGeometryTest { assertEquals(0.75f, RotationGeometry.stableAspect(1.3333f, 270), 1e-3f) } + @Test + fun stableAspect_negativeAndMultipleRotations_invertsCorrectly() { + // -450° (即 270°) 应与 90° 一致,反转宽高比 + assertEquals(0.75f, RotationGeometry.stableAspect(1.3333f, -450), 1e-3f) + assertEquals(1.3333f, RotationGeometry.stableAspect(1.3333f, -360), 1e-3f) + } + @Test fun coverScale_atStableOffset_isOne() { // 稳态(offset=0)零裁剪零黑边