Skip to content

Commit ba8562b

Browse files
Merge branch 'feature/image-with-constraints' into develop
2 parents 73bf732 + 1fb6bd9 commit ba8562b

File tree

2 files changed

+419
-0
lines changed

2 files changed

+419
-0
lines changed
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package com.smarttoolfactory.image
2+
3+
import android.graphics.Bitmap
4+
import androidx.compose.foundation.Canvas
5+
import androidx.compose.runtime.Composable
6+
import androidx.compose.runtime.Stable
7+
import androidx.compose.runtime.remember
8+
import androidx.compose.ui.graphics.Canvas
9+
import androidx.compose.ui.graphics.ImageBitmap
10+
import androidx.compose.ui.graphics.asAndroidBitmap
11+
import androidx.compose.ui.graphics.asImageBitmap
12+
import androidx.compose.ui.layout.ContentScale
13+
import androidx.compose.ui.unit.Constraints
14+
import androidx.compose.ui.unit.Density
15+
import androidx.compose.ui.unit.Dp
16+
import androidx.compose.ui.unit.IntRect
17+
18+
19+
/**
20+
* Receiver scope being used by the children parameter of [ImageWithConstraints]
21+
*/
22+
@Stable
23+
interface ImageScope {
24+
/**
25+
* The constraints given by the parent layout in pixels.
26+
*
27+
* Use [minWidth], [maxWidth], [minHeight] or [maxHeight] if you need value in [Dp].
28+
*/
29+
val constraints: Constraints
30+
31+
/**
32+
* The minimum width in [Dp].
33+
*
34+
* @see constraints for the values in pixels.
35+
*/
36+
val minWidth: Dp
37+
38+
/**
39+
* The maximum width in [Dp].
40+
*
41+
* @see constraints for the values in pixels.
42+
*/
43+
val maxWidth: Dp
44+
45+
/**
46+
* The minimum height in [Dp].
47+
*
48+
* @see constraints for the values in pixels.
49+
*/
50+
val minHeight: Dp
51+
52+
/**
53+
* The maximum height in [Dp].
54+
*
55+
* @see constraints for the values in pixels.
56+
*/
57+
val maxHeight: Dp
58+
59+
/**
60+
* Width of area inside BoxWithConstraints that is scaled based on [ContentScale]
61+
* This is width of the [Canvas] draw draws [ImageBitmap]
62+
*/
63+
val imageWidth: Dp
64+
65+
/**
66+
* Height of area inside BoxWithConstraints that is scaled based on [ContentScale]
67+
* This is height of the [Canvas] draw draws [ImageBitmap]
68+
*/
69+
val imageHeight: Dp
70+
71+
/**
72+
* [IntRect] that covers boundaries of [ImageBitmap]
73+
*/
74+
val rect: IntRect
75+
}
76+
77+
internal data class ImageScopeImpl(
78+
private val density: Density,
79+
override val constraints: Constraints,
80+
override val imageWidth: Dp,
81+
override val imageHeight: Dp,
82+
override val rect: IntRect,
83+
) : ImageScope {
84+
85+
override val minWidth: Dp get() = with(density) { constraints.minWidth.toDp() }
86+
87+
override val maxWidth: Dp
88+
get() = with(density) {
89+
if (constraints.hasBoundedWidth) constraints.maxWidth.toDp() else Dp.Infinity
90+
}
91+
92+
override val minHeight: Dp get() = with(density) { constraints.minHeight.toDp() }
93+
94+
override val maxHeight: Dp
95+
get() = with(density) {
96+
if (constraints.hasBoundedHeight) constraints.maxHeight.toDp() else Dp.Infinity
97+
}
98+
}
99+
100+
@Composable
101+
internal fun ImageScope.getScaledImageBitmap(
102+
bitmap: ImageBitmap,
103+
contentScale: ContentScale
104+
): ImageBitmap {
105+
106+
val scaledBitmap =
107+
remember(bitmap, rect, imageWidth, imageHeight, contentScale) {
108+
// This bitmap is needed when we crop original bitmap due to scaling mode
109+
// and aspect ratio result of cropping
110+
// We might have center section of the image after cropping, and
111+
// because of that thumbLayout either should have rectangle and some
112+
// complex calculation for srcOffset and srcSide along side with touch offset
113+
// or we can create a new bitmap that only contains area bounded by rectangle
114+
Bitmap.createBitmap(
115+
bitmap.asAndroidBitmap(),
116+
rect.left,
117+
rect.top,
118+
rect.width,
119+
rect.height
120+
).asImageBitmap()
121+
}
122+
return scaledBitmap
123+
}

0 commit comments

Comments
 (0)