In addition to the`Canvas`composable, Compose has several useful graphics`Modifiers`which aid in drawing custom content. These modifiers are useful because they can be applied to any composable.

## Drawing modifiers

All drawing commands are done with a drawing modifier in Compose. There are three main drawing modifiers in Compose:

- [`drawWithContent`](https://developer.android.com/reference/kotlin/androidx/compose/ui/draw/package-summary#(androidx.compose.ui.Modifier).drawWithContent(kotlin.Function1))
- [`drawBehind`](https://developer.android.com/reference/kotlin/androidx/compose/ui/draw/package-summary#(androidx.compose.ui.Modifier).drawBehind(kotlin.Function1))
- [`drawWithCache`](https://developer.android.com/reference/kotlin/androidx/compose/ui/draw/package-summary#(androidx.compose.ui.Modifier).drawWithCache(kotlin.Function1))

The base modifier for drawing is`drawWithContent`, where you can decide the drawing order of your Composable and the drawing commands issued inside the modifier.`drawBehind`is a convenient wrapper around`drawWithContent`which has the drawing order set to behind the content of the composable.`drawWithCache`calls either`onDrawBehind`or`onDrawWithContent`inside of it - and provides a mechanism for caching the objects created in them.

### `Modifier.drawWithContent`: Choose drawing order

[`Modifier.drawWithContent`](https://developer.android.com/reference/kotlin/androidx/compose/ui/draw/package-summary#(androidx.compose.ui.Modifier).drawWithContent(kotlin.Function1))lets you execute[`DrawScope`](https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/drawscope/DrawScope)operations before or after the content of the composable. Be sure to call`drawContent`to then render the actual content of the composable. With this modifier, you can decide the order of operations, if you want your content to be drawn before or after your custom drawing operations.

For example, if you wished to render a radial gradient on top of your content to create a flashlight keyhole effect on the UI, you could do the following:

<br />

```kotlin
var pointerOffset by remember {
    mutableStateOf(Offset(0f, 0f))
}
Column(
    modifier = Modifier
        .fillMaxSize()
        .pointerInput("dragging") {
            detectDragGestures { change, dragAmount ->
                pointerOffset += dragAmount
            }
        }
        .onSizeChanged {
            pointerOffset = Offset(it.width / 2f, it.height / 2f)
        }
        .drawWithContent {
            drawContent()
            // draws a fully black area with a small keyhole at pointerOffset that'll show part of the UI.
            drawRect(
                Brush.radialGradient(
                    listOf(Color.Transparent, Color.Black),
                    center = pointerOffset,
                    radius = 100.dp.toPx(),
                )
            )
        }
) {
    // Your composables here
}https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L103-L130
```

<br />

**Figure 1**: Modifier.drawWithContent used on top of a Composable to create a flashlight type UI experience.

### `Modifier.drawBehind`: Drawing behind a composable

[`Modifier.drawBehind`](https://developer.android.com/reference/kotlin/androidx/compose/ui/draw/package-summary#(androidx.compose.ui.Modifier).drawBehind(kotlin.Function1))lets you perform`DrawScope`operations behind the composable content that is drawn on screen. If you take a look at the implementation of[`Canvas`](https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/Canvas), you might notice that it is just a convenient wrapper around`Modifier.drawBehind`.

To draw a rounded rectangle behind`Text`:

<br />

```kotlin
Text(
    "Hello Compose!",
    modifier = Modifier
        .drawBehind {
            drawRoundRect(
                Color(0xFFBBAAEE),
                cornerRadius = CornerRadius(10.dp.toPx())
            )
        }
        .padding(4.dp)
)https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L138-L148
```

<br />

Which produces the following result:
![Text and a background drawn using Modifier.drawBehind](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/modifier_draw_behind.png)**Figure 2**: Text and a background drawn using Modifier.drawBehind

### `Modifier.drawWithCache`: Drawing and caching draw objects

[`Modifier.drawWithCache`](https://developer.android.com/reference/kotlin/androidx/compose/ui/draw/package-summary#(androidx.compose.ui.Modifier).drawWithCache(kotlin.Function1))keeps the objects that are created inside of it cached. The objects are cached as long as the size of the drawing area is the same, or any state objects that are read have not changed. This modifier is useful for improving performance of drawing calls as it avoids the need to reallocate objects (such as:`Brush, Shader, Path`etc.) that are created on draw.

Alternatively, you could also cache objects using`remember`, outside of the modifier. However, this is not always possible as you don't always have access to the composition. It can be more performant to use`drawWithCache`if the objects are only used for drawing.
| **Note:** Only use`Modifier.drawWithCache`when you're creating objects that must be cached. Using this modifier without needing to cache objects, can result in unnecessary lambda allocations.

For example, if you create a`Brush`to draw a gradient behind a`Text`, using`drawWithCache`caches the`Brush`object until the size of the drawing area changes:

<br />

```kotlin
Text(
    "Hello Compose!",
    modifier = Modifier
        .drawWithCache {
            val brush = Brush.linearGradient(
                listOf(
                    Color(0xFF9E82F0),
                    Color(0xFF42A5F5)
                )
            )
            onDrawBehind {
                drawRoundRect(
                    brush,
                    cornerRadius = CornerRadius(10.dp.toPx())
                )
            }
        }
)https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L156-L173
```

<br />

![Caching the Brush object with drawWithCache](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/modifier_draw_with_cache.png)**Figure 3**: Caching the Brush object with drawWithCache

## Graphics modifiers

### `Modifier.graphicsLayer`: Apply transformations to composables

[`Modifier.graphicsLayer`](https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/package-summary#(androidx.compose.ui.Modifier.graphicsLayer(kotlin.Float,kotlin.Float,kotlin.Float,kotlin.Float,kotlin.Float,kotlin.Float,kotlin.Float,kotlin.Float,kotlin.Float,kotlin.Float,androidx.compose.ui.graphics.TransformOrigin,androidx.compose.ui.graphics.Shape,kotlin.Boolean,androidx.compose.ui.graphics.RenderEffect,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.Color,androidx.compose.ui.graphics.CompositingStrategy)))is a modifier that makes the content of the composable draw into a draw layer. A layer provides a few different functions, such as:

- Isolation for its drawing instructions (similar to[`RenderNode`](https://developer.android.com/reference/android/graphics/RenderNode)). Drawing instructions captured as part of a layer can be re-issued efficiently by the rendering pipeline without re-executing application code.
- Transformations that apply to all the drawing instructions contained within a layer.
- Rasterization for composition capabilities. When a layer is rasterized, its drawing instructions are executed and the output is captured into an offscreen buffer.[Compositing](https://developer.android.com/develop/ui/compose/graphics/draw/modifiers#heading=%7B:compositing-strategy%7D)such a buffer for subsequent frames is faster than executing the individual instructions, but it will behave as a bitmap when transforms like scaling or rotation are applied.

#### Transformations

`Modifier.graphicsLayer`provides isolation for its drawing instructions; for instance, various transformations can be applied using`Modifier.graphicsLayer`. These can be animated or modified without needing to re-execute the drawing lambda.

`Modifier.graphicsLayer`does not change the measured size or placement of your composable, as it only affects the draw phase. This means that your composable might overlap others if it ends up drawing outside of its layout bounds.
| **Note:** You should prefer the lambda version of this modifier when performing animations or using a`State`object to update a`graphicsLayer`property.

The following transformations can be applied with this modifier:

##### Scale - increase size

`scaleX`and`scaleY`enlarges or shrinks content in the horizontal or vertical direction, respectively. A value of`1.0f`indicates no change in scale, a value of`0.5f`means half of the dimension.

<br />

```kotlin
Image(
    painter = painterResource(id = R.drawable.sunset),
    contentDescription = "Sunset",
    modifier = Modifier
        .graphicsLayer {
            this.scaleX = 1.2f
            this.scaleY = 0.8f
        }
)https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L181-L189
```

<br />

**Figure 4**: scaleX and scaleY applied to an Image composable

##### Translation

`translationX`and`translationY`can be changed with`graphicsLayer`,`translationX`moves the composable left or right.`translationY`moves the composable up or down.

<br />

```kotlin
Image(
    painter = painterResource(id = R.drawable.sunset),
    contentDescription = "Sunset",
    modifier = Modifier
        .graphicsLayer {
            this.translationX = 100.dp.toPx()
            this.translationY = 10.dp.toPx()
        }
)https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L197-L205
```

<br />

**Figure 5**: translationX and translationY applied to Image with Modifier.graphicsLayer

##### Rotation

Set`rotationX`to rotate horizontally,`rotationY`to rotate vertically and`rotationZ`to rotate on the Z axis (standard rotation). This value is specified in degrees (0-360).

<br />

```kotlin
Image(
    painter = painterResource(id = R.drawable.sunset),
    contentDescription = "Sunset",
    modifier = Modifier
        .graphicsLayer {
            this.rotationX = 90f
            this.rotationY = 275f
            this.rotationZ = 180f
        }
)https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L213-L222
```

<br />

**Figure 6**: rotationX, rotationY and rotationZ set on Image by Modifier.graphicsLayer

##### Origin

A`transformOrigin`can be specified. It is then used as the point from which transformations take place. All the examples so far have used`TransformOrigin.Center`, which is at`(0.5f, 0.5f)`. If you specify the origin at`(0f, 0f)`, the transformations then start from the top-left corner of the composable.

If you change the origin with a`rotationZ`transformation, you can see that the item rotates around the top left of the composable:

<br />

```kotlin
Image(
    painter = painterResource(id = R.drawable.sunset),
    contentDescription = "Sunset",
    modifier = Modifier
        .graphicsLayer {
            this.transformOrigin = TransformOrigin(0f, 0f)
            this.rotationX = 90f
            this.rotationY = 275f
            this.rotationZ = 180f
        }
)https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L230-L240
```

<br />

**Figure 7**: Rotation applied with TransformOrigin set to 0f, 0f

#### Clip and Shape

Shape specifies the outline that the content clips to when`clip = true`. In this example, we set two boxes to have two different clips - one using`graphicsLayer`clip variable, and the other using the convenient wrapper`Modifier.clip`.

<br />

```kotlin
Column(modifier = Modifier.padding(16.dp)) {
    Box(
        modifier = Modifier
            .size(200.dp)
            .graphicsLayer {
                clip = true
                shape = CircleShape
            }
            .background(Color(0xFFF06292))
    ) {
        Text(
            "Hello Compose",
            style = TextStyle(color = Color.Black, fontSize = 46.sp),
            modifier = Modifier.align(Alignment.Center)
        )
    }
    Box(
        modifier = Modifier
            .size(200.dp)
            .clip(CircleShape)
            .background(Color(0xFF4DB6AC))
    )
}https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L248-L270
```

<br />

The contents of the first box (the text saying "Hello Compose") are clipped to the circle shape:
![Clip applied to Box composable](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/clip_applied.png)**Figure 8**: Clip applied to Box composable

If you then apply a`translationY`to the top pink circle, you see that the bounds of the Composable are still the same, but the circle draws underneath the bottom circle (and outside of its bounds).
![Clip applied with translationY, and red border for outline](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/clip_applied_red_border.png)**Figure 9**: Clip applied with translationY, and red border for outline

To clip the composable to the region it's drawn in, you can add another`Modifier.clip(RectangleShape)`at the start of the modifier chain. The content then remains inside of the original bounds.

<br />

```kotlin
Column(modifier = Modifier.padding(16.dp)) {
    Box(
        modifier = Modifier
            .clip(RectangleShape)
            .size(200.dp)
            .border(2.dp, Color.Black)
            .graphicsLayer {
                clip = true
                shape = CircleShape
                translationY = 50.dp.toPx()
            }
            .background(Color(0xFFF06292))
    ) {
        Text(
            "Hello Compose",
            style = TextStyle(color = Color.Black, fontSize = 46.sp),
            modifier = Modifier.align(Alignment.Center)
        )
    }

    Box(
        modifier = Modifier
            .size(200.dp)
            .clip(RoundedCornerShape(500.dp))
            .background(Color(0xFF4DB6AC))
    )
}https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L274-L300
```

<br />

![Clip applied on top of graphicsLayer transformation](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/clip_applied_everything.png)**Figure 10**: Clip applied on top of graphicsLayer transformation

#### Alpha

`Modifier.graphicsLayer`can be used to set an`alpha`(opacity) for the whole layer.`1.0f`is fully opaque and`0.0f`is invisible.

<br />

```kotlin
Image(
    painter = painterResource(id = R.drawable.sunset),
    contentDescription = "clock",
    modifier = Modifier
        .graphicsLayer {
            this.alpha = 0.5f
        }
)https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L308-L315
```

<br />

![Image with alpha applied](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/image_alpha.png)**Figure 11**: Image with alpha applied**Note:** When an alpha is set to less than 1.0f, the entire contents of the layer are drawn to an offscreen buffer (if the[`CompositingStrategy`](https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/CompositingStrategy)is not set to[`ModulateAlpha`](https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/CompositingStrategy#ModulateAlpha())). See the`CompositingStrategy`section for more information.

#### Compositing strategy

Working with alpha and transparency might not be as simple as changing a single alpha value. In addition to changing an alpha, there is also the option to set a[`CompositingStrategy`](https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/CompositingStrategy)on a`graphicsLayer`. A`CompositingStrategy`determines how the content of the composable is composited (put together) with the other content already drawn on screen.
| **Note:** `CompositingStrategy`was introduced in Compose`1.4.0-alpha02`.

The different strategies are:

##### Auto (default)

The[compositing strategy](https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/CompositingStrategy#Auto())is determined by the rest of the`graphicsLayer`parameters. It renders the layer into an offscreen buffer if alpha is less than 1.0f or a`RenderEffect`is set. Whenever the alpha is less than 1f, a compositing layer is created automatically to render the contents and then draw this offscreen buffer to the destination with the corresponding alpha. Setting a[`RenderEffect`](https://developer.android.com/reference/android/graphics/RenderEffect)or overscroll always renders content into an offscreen buffer regardless of the`CompositingStrategy`set.

##### Offscreen

The contents of the composable are**always** rasterized to an offscreen texture or bitmap before rendering to the destination. This is useful for applying[`BlendMode`](https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/BlendMode)operations to mask content, and for performance when rendering complex sets of drawing instructions.

An example of using[`CompositingStrategy.Offscreen`](https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/CompositingStrategy#Offscreen())is with`BlendModes`. Taking a look at the example below, say you want to remove parts of an`Image`composable by issuing a draw command that uses`BlendMode.Clear`. If you do not set the`compositingStrategy`to`CompositingStrategy.Offscreen`, the`BlendMode`interacts with all the contents below it.

<br />

```kotlin
Image(
    painter = painterResource(id = R.drawable.dog),
    contentDescription = "Dog",
    contentScale = ContentScale.Crop,
    modifier = Modifier
        .size(120.dp)
        .aspectRatio(1f)
        .background(
            Brush.linearGradient(
                listOf(
                    Color(0xFFC5E1A5),
                    Color(0xFF80DEEA)
                )
            )
        )
        .padding(8.dp)
        .graphicsLayer {
            compositingStrategy = CompositingStrategy.Offscreen
        }
        .drawWithCache {
            val path = Path()
            path.addOval(
                Rect(
                    topLeft = Offset.Zero,
                    bottomRight = Offset(size.width, size.height)
                )
            )
            onDrawWithContent {
                clipPath(path) {
                    // this draws the actual image - if you don't call drawContent, it wont
                    // render anything
                    this@onDrawWithContent.drawContent()
                }
                val dotSize = size.width / 8f
                // Clip a white border for the content
                drawCircle(
                    Color.Black,
                    radius = dotSize,
                    center = Offset(
                        x = size.width - dotSize,
                        y = size.height - dotSize
                    ),
                    blendMode = BlendMode.Clear
                )
                // draw the red circle indication
                drawCircle(
                    Color(0xFFEF5350), radius = dotSize * 0.8f,
                    center = Offset(
                        x = size.width - dotSize,
                        y = size.height - dotSize
                    )
                )
            }
        }
)https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L323-L378
```

<br />

By setting the`CompositingStrategy`to`Offscreen`, it creates an offscreen texture to execute the commands to (applying the`BlendMode`only to the contents of this composable). It then renders it on top of what is already rendered on screen, not affecting the content already drawn.
![Modifier.drawWithContent on an Image showing a circle indication, with the BlendMode.Clear inside app](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/complex_modifier_example_drawWithCache_background.png)**Figure 12**: Modifier.drawWithContent on an Image showing a circle indication, with the BlendMode.Clear and CompositingStrategy.Offscreen inside app

If you didn't use`CompositingStrategy.Offscreen`, the results of applying`BlendMode.Clear`clears all the pixels in the destination, regardless of what was already set-- leaving the window's rendering buffer (black) visible. Many of the`BlendModes`that involve alpha won't work as expected without an offscreen buffer. Note the black ring around the red circle indicator:
![Modifier.drawWithContent on an Image showing a circle indication, with the BlendMode.Clear and no CompositingStrategy set](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/blendmode_without_compositing_strategy.png)**Figure 13**: Modifier.drawWithContent on an Image showing a circle indication, with the BlendMode.Clear and no CompositingStrategy set

To understand this a bit further: if the app had a translucent window background, and you did not use the`CompositingStrategy.Offscreen`, the`BlendMode`would interact with the whole app. It would clear all of the pixels to show the app or wallpaper underneath, as in this example:
![No CompositingStrategy set and using BlendMode.Clear with an app that has a translucent window background. The pink wallpaper is shown through the area around the red status circle.](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/compositing_strategy_punch_through_to_wallpaper.png)**Figure 14**: No CompositingStrategy set and using BlendMode.Clear with an app that has a translucent window background. Notice how the pink wallpaper is shown through the area around the red status circle.

It's worth noting that when using`CompositingStrategy.Offscreen`, an offscreen texture that is the size of the drawing area is created and rendered back on screen. Any drawing commands that are done with this strategy, are by default be clipped to this region. The below code snippet illustrates the differences when switching to using offscreen textures:

<br />

```kotlin
@Composable
fun CompositingStrategyExamples() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .wrapContentSize(Alignment.Center)
    ) {
        // Does not clip content even with a graphics layer usage here. By default, graphicsLayer
        // does not allocate + rasterize content into a separate layer but instead is used
        // for isolation. That is draw invalidations made outside of this graphicsLayer will not
        // re-record the drawing instructions in this composable as they have not changed
        Canvas(
            modifier = Modifier
                .graphicsLayer()
                .size(100.dp) // Note size of 100 dp here
                .border(2.dp, color = Color.Blue)
        ) {
            // ... and drawing a size of 200 dp here outside the bounds
            drawRect(color = Color.Magenta, size = Size(200.dp.toPx(), 200.dp.toPx()))
        }

        Spacer(modifier = Modifier.size(300.dp))

        /* Clips content as alpha usage here creates an offscreen buffer to rasterize content
        into first then draws to the original destination */
        Canvas(
            modifier = Modifier
                // force to an offscreen buffer
                .graphicsLayer(compositingStrategy = CompositingStrategy.Offscreen)
                .size(100.dp) // Note size of 100 dp here
                .border(2.dp, color = Color.Blue)
        ) {
            /* ... and drawing a size of 200 dp. However, because of the CompositingStrategy.Offscreen usage above, the
            content gets clipped */
            drawRect(color = Color.Red, size = Size(200.dp.toPx(), 200.dp.toPx()))
        }
    }
}https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L384-L421
```

<br />

![CompositingStrategy.Auto vs CompositingStrategy.Offscreen - offscreen clips to the region, where auto doesn’t](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/graphics_compositing_strategy.png)**Figure 15**: CompositingStrategy.Auto vs CompositingStrategy.Offscreen - offscreen clips to the region, where auto doesn't

##### `ModulateAlpha`

This[composition strategy](https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/CompositingStrategy#ModulateAlpha())modulates the alpha for each of the drawing instructions recorded within the`graphicsLayer`. It won't create an offscreen buffer for alpha below 1.0f unless a`RenderEffect`is set, so it can be more efficient for alpha rendering. However, it can provide different results for overlapping content. For use cases where it is known in advance that content is not overlapping, this can provide better performance than`CompositingStrategy.Auto`with alpha values less than 1.

Another example of different composition strategies is below - applying different alphas to different parts of the composables, and applying a`Modulate`strategy:

<br />

```kotlin
@Preview
@Composable
fun CompositingStrategy_ModulateAlpha() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(32.dp)
    ) {
        // Base drawing, no alpha applied
        Canvas(
            modifier = Modifier.size(200.dp)
        ) {
            drawSquares()
        }

        Spacer(modifier = Modifier.size(36.dp))

        // Alpha 0.5f applied to whole composable
        Canvas(
            modifier = Modifier
                .size(200.dp)
                .graphicsLayer {
                    alpha = 0.5f
                }
        ) {
            drawSquares()
        }
        Spacer(modifier = Modifier.size(36.dp))

        // 0.75f alpha applied to each draw call when using ModulateAlpha
        Canvas(
            modifier = Modifier
                .size(200.dp)
                .graphicsLayer {
                    compositingStrategy = CompositingStrategy.ModulateAlpha
                    alpha = 0.75f
                }
        ) {
            drawSquares()
        }
    }
}

private fun DrawScope.drawSquares() {

    val size = Size(100.dp.toPx(), 100.dp.toPx())
    drawRect(color = Red, size = size)
    drawRect(
        color = Purple, size = size,
        topLeft = Offset(size.width / 4f, size.height / 4f)
    )
    drawRect(
        color = Yellow, size = size,
        topLeft = Offset(size.width / 4f * 2f, size.height / 4f * 2f)
    )
}

val Purple = Color(0xFF7E57C2)
val Yellow = Color(0xFFFFCA28)
val Red = Color(0xFFEF5350)https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L425-L484
```

<br />

![ModulateAlpha applies the alpha set to each individual draw command](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/modulate_alpha.png)**Figure 16**: ModulateAlpha applies the alpha set to each individual draw command

## Write contents of a composable to a bitmap

| **Note:** The`rememberGraphicsLayer()`function used in this snippet is only available from Compose 1.7.0-alpha07+.

A common use case is to create a`Bitmap`from a composable. To copy the contents of your composable to a`Bitmap`, create a`GraphicsLayer`using`rememberGraphicsLayer()`.

Redirect the drawing commands to the new layer using`drawWithContent()`and`graphicsLayer.record{}`. Then draw the layer in the visible canvas using`drawLayer`:

<br />

```kotlin
val coroutineScope = rememberCoroutineScope()
val graphicsLayer = rememberGraphicsLayer()
Box(
    modifier = Modifier
        .drawWithContent {
            // call record to capture the content in the graphics layer
            graphicsLayer.record {
                // draw the contents of the composable into the graphics layer
                this@drawWithContent.drawContent()
            }
            // draw the graphics layer on the visible canvas
            drawLayer(graphicsLayer)
        }
        .clickable {
            coroutineScope.launch {
                val bitmap = graphicsLayer.toImageBitmap()
                // do something with the newly acquired bitmap
            }
        }
        .background(Color.White)
) {
    Text("Hello Android", fontSize = 26.sp)
}https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/AdvancedGraphicsSnippets.kt#L94-L116
```

<br />

You can save the bitmap to disk and share it. For more details, see the[full example snippet](https://github.com/android/snippets/blob/latest/compose/snippets/src/main/java/com/example/compose/snippets/graphics/AdvancedGraphicsSnippets.kt#L123). Be sure to check for on device permissions before trying to save to disk.

## Custom drawing modifier

To create your own custom modifier, implement the`DrawModifier`interface. This gives you access to a`ContentDrawScope`, which is the same as what is exposed when using`Modifier.drawWithContent()`. You can then extract common drawing operations to custom drawing modifiers to clean up the code and provide convenient wrappers; for example,`Modifier.background()`is a convenient`DrawModifier`.

For example, if you wanted to implement a`Modifier`that vertically flips content, you can create one as follows:

<br />

```kotlin
class FlippedModifier : DrawModifier {
    override fun ContentDrawScope.draw() {
        scale(1f, -1f) {
            this@draw.drawContent()
        }
    }
}

fun Modifier.flipped() = this.then(FlippedModifier())https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L488-L496
```

<br />

Then use this flipped modifier applied on`Text`:

<br />

```kotlin
Text(
    "Hello Compose!",
    modifier = Modifier
        .flipped()
)https://github.com/android/snippets/blob/95aeebd507b29719a9e7d5a839f101bbbe42ea72/compose/snippets/src/main/java/com/example/compose/snippets/graphics/GraphicsModifiersSnippets.kt#L503-L507
```

<br />

![Custom Flipped Modifier on Text](https://developer.android.com/static/develop/ui/compose/images/graphics/modifiers/modifier_flipped.png)**Figure 17**: Custom Flipped Modifier on Text

## Additional resources

For more examples using`graphicsLayer`and custom drawing, check out the following resources:

- [Making Jellyfish move in Compose](https://medium.com/androiddevelopers/making-jellyfish-move-in-compose-animating-imagevectors-and-applying-agsl-rendereffects-3666596a8888)
- [ADS 2022 Layouts and Graphics in Compose](https://youtu.be/xcfEQO0k_gU)

## Recommended for you

- Note: link text is displayed when JavaScript is off
- [Graphics in Compose](https://developer.android.com/develop/ui/compose/graphics/draw/overview)
- [Customize an image {:#customize-image}](https://developer.android.com/develop/ui/compose/graphics/images/customize)
- [Kotlin for Jetpack Compose](https://developer.android.com/develop/ui/compose/kotlin)