@@ -7,9 +7,13 @@ import androidx.compose.ui.Modifier
77import androidx.compose.ui.geometry.Rect
88import androidx.compose.ui.graphics.*
99import androidx.compose.ui.graphics.drawscope.Stroke
10+ import androidx.compose.ui.graphics.drawscope.translate
11+ import androidx.compose.ui.platform.LocalDensity
12+ import androidx.compose.ui.platform.LocalLayoutDirection
1013import androidx.compose.ui.unit.Dp
1114import androidx.compose.ui.unit.IntOffset
1215import androidx.compose.ui.unit.IntSize
16+ import androidx.compose.ui.unit.LayoutDirection
1317import com.smarttoolfactory.cropper.util.drawGrid
1418import kotlin.math.roundToInt
1519
@@ -20,80 +24,98 @@ import kotlin.math.roundToInt
2024@Composable
2125internal fun DrawingOverlay (
2226 modifier : Modifier ,
23- drawOverlay : Boolean ,
27+ drawOverlay : Boolean ,
2428 rect : Rect ,
29+ shape : Shape ,
2530 drawGrid : Boolean ,
2631 overlayColor : Color ,
2732 handleColor : Color ,
2833 strokeWidth : Dp ,
2934 drawHandles : Boolean ,
3035 handleSize : Float
3136) {
37+ val density = LocalDensity .current
38+ val layoutDirection: LayoutDirection = LocalLayoutDirection .current
3239
33- val path = remember(rect, handleSize) {
34- Path ().apply {
35-
36- if (rect != Rect .Zero ) {
37- // Top left lines
38- moveTo(rect.topLeft.x, rect.topLeft.y + handleSize)
39- lineTo(rect.topLeft.x, rect.topLeft.y)
40- lineTo(rect.topLeft.x + handleSize, rect.topLeft.y)
41-
42- // Top right lines
43- moveTo(rect.topRight.x - handleSize, rect.topRight.y)
44- lineTo(rect.topRight.x, rect.topRight.y)
45- lineTo(rect.topRight.x, rect.topRight.y + handleSize)
46-
47- // Bottom right lines
48- moveTo(rect.bottomRight.x, rect.bottomRight.y - handleSize)
49- lineTo(rect.bottomRight.x, rect.bottomRight.y)
50- lineTo(rect.bottomRight.x - handleSize, rect.bottomRight.y)
51-
52- // Bottom left lines
53- moveTo(rect.bottomLeft.x + handleSize, rect.bottomLeft.y)
54- lineTo(rect.bottomLeft.x, rect.bottomLeft.y)
55- lineTo(rect.bottomLeft.x, rect.bottomLeft.y - handleSize)
56- }
57- }
40+ val pathHandles = remember {
41+ Path ()
42+ }
43+
44+ // TODO Update with a way that doesn't create new object on recomposition
45+ val outline = remember(rect, shape) {
46+ shape.createOutline(rect.size, layoutDirection, density)
5847 }
5948
6049 Canvas (modifier = modifier) {
6150 val strokeWidthPx = strokeWidth.toPx()
6251
52+
6353 with (drawContext.canvas.nativeCanvas) {
6454 val checkPoint = saveLayer(null , null )
6555
6656 // Destination
6757 drawRect(Color (0x77000000 ))
6858
6959 // Source
70- drawRect(
71- topLeft = rect.topLeft,
72- size = rect.size,
73- color = Color .Transparent ,
74- blendMode = BlendMode .Clear
75- )
60+ translate(left = rect.left, top = rect.top) {
61+ drawOutline(
62+ outline = outline,
63+ color = Color .Transparent ,
64+ blendMode = BlendMode .SrcOut
65+ )
66+ }
67+
68+ if (drawGrid) {
69+ drawGrid(
70+ rect = rect,
71+ strokeWidth = strokeWidthPx,
72+ color = overlayColor
73+ )
74+ }
75+
7676 restoreToCount(checkPoint)
7777 }
7878
79- if (drawOverlay){
79+ if (drawOverlay) {
8080 drawRect(
8181 topLeft = rect.topLeft,
8282 size = rect.size,
8383 color = overlayColor,
8484 style = Stroke (width = strokeWidthPx)
8585 )
8686
87- if (drawGrid) {
88- drawGrid(rect = rect, strokeWidth = strokeWidthPx / 2 , color = overlayColor)
89- }
90-
9187 if (drawHandles) {
88+ pathHandles.apply {
89+ reset()
90+
91+ if (rect != Rect .Zero ) {
92+ // Top left lines
93+ moveTo(rect.topLeft.x, rect.topLeft.y + handleSize)
94+ lineTo(rect.topLeft.x, rect.topLeft.y)
95+ lineTo(rect.topLeft.x + handleSize, rect.topLeft.y)
96+
97+ // Top right lines
98+ moveTo(rect.topRight.x - handleSize, rect.topRight.y)
99+ lineTo(rect.topRight.x, rect.topRight.y)
100+ lineTo(rect.topRight.x, rect.topRight.y + handleSize)
101+
102+ // Bottom right lines
103+ moveTo(rect.bottomRight.x, rect.bottomRight.y - handleSize)
104+ lineTo(rect.bottomRight.x, rect.bottomRight.y)
105+ lineTo(rect.bottomRight.x - handleSize, rect.bottomRight.y)
106+
107+ // Bottom left lines
108+ moveTo(rect.bottomLeft.x + handleSize, rect.bottomLeft.y)
109+ lineTo(rect.bottomLeft.x, rect.bottomLeft.y)
110+ lineTo(rect.bottomLeft.x, rect.bottomLeft.y - handleSize)
111+ }
112+ }
113+
92114 drawPath(
93- path = path ,
115+ path = pathHandles ,
94116 color = handleColor,
95117 style = Stroke (
96- width= strokeWidthPx * 2 ,
118+ width = strokeWidthPx * 2 ,
97119 cap = StrokeCap .Round ,
98120 join = StrokeJoin .Round
99121 )
@@ -129,4 +151,3 @@ internal fun ImageOverlay(
129151 )
130152 }
131153}
132-
0 commit comments