1 /*
<lambda>null2  * Copyright 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.compose.foundation
18 
19 import androidx.compose.runtime.Composable
20 import androidx.compose.runtime.NonRestartableComposable
21 import androidx.compose.runtime.remember
22 import androidx.compose.ui.Alignment
23 import androidx.compose.ui.Modifier
24 import androidx.compose.ui.draw.clipToBounds
25 import androidx.compose.ui.draw.paint
26 import androidx.compose.ui.graphics.ColorFilter
27 import androidx.compose.ui.graphics.DefaultAlpha
28 import androidx.compose.ui.graphics.FilterQuality
29 import androidx.compose.ui.graphics.ImageBitmap
30 import androidx.compose.ui.graphics.drawscope.DrawScope.Companion.DefaultFilterQuality
31 import androidx.compose.ui.graphics.painter.BitmapPainter
32 import androidx.compose.ui.graphics.painter.ColorPainter
33 import androidx.compose.ui.graphics.painter.Painter
34 import androidx.compose.ui.graphics.vector.ImageVector
35 import androidx.compose.ui.graphics.vector.rememberVectorPainter
36 import androidx.compose.ui.layout.ContentScale
37 import androidx.compose.ui.layout.Layout
38 import androidx.compose.ui.semantics.Role
39 import androidx.compose.ui.semantics.contentDescription
40 import androidx.compose.ui.semantics.role
41 import androidx.compose.ui.semantics.semantics
42 
43 /**
44  * A composable that lays out and draws a given [ImageBitmap]. This will attempt to size the
45  * composable according to the [ImageBitmap]'s given width and height. However, an optional
46  * [Modifier] parameter can be provided to adjust sizing or draw additional content (ex.
47  * background). Any unspecified dimension will leverage the [ImageBitmap]'s size as a minimum
48  * constraint.
49  *
50  * The following sample shows basic usage of an Image composable to position and draw an
51  * [ImageBitmap] on screen
52  *
53  * @sample androidx.compose.foundation.samples.ImageSample
54  *
55  * For use cases that require drawing a rectangular subset of the [ImageBitmap] consumers can use
56  * overload that consumes a [Painter] parameter shown in this sample
57  *
58  * @sample androidx.compose.foundation.samples.BitmapPainterSubsectionSample
59  * @param bitmap The [ImageBitmap] to draw
60  * @param contentDescription text used by accessibility services to describe what this image
61  *   represents. This should always be provided unless this image is used for decorative purposes,
62  *   and does not represent a meaningful action that a user can take. This text should be localized,
63  *   such as by using [androidx.compose.ui.res.stringResource] or similar
64  * @param modifier Modifier used to adjust the layout algorithm or draw decoration content (ex.
65  *   background)
66  * @param alignment Optional alignment parameter used to place the [ImageBitmap] in the given bounds
67  *   defined by the width and height
68  * @param contentScale Optional scale parameter used to determine the aspect ratio scaling to be
69  *   used if the bounds are a different size from the intrinsic size of the [ImageBitmap]
70  * @param alpha Optional opacity to be applied to the [ImageBitmap] when it is rendered onscreen
71  * @param colorFilter Optional ColorFilter to apply for the [ImageBitmap] when it is rendered
72  *   onscreen
73  */
74 @Composable
75 @Deprecated(
76     "Consider usage of the Image composable that consumes an optional FilterQuality parameter",
77     level = DeprecationLevel.HIDDEN,
78     replaceWith =
79         ReplaceWith(
80             expression =
81                 "Image(bitmap, contentDescription, modifier, alignment, contentScale, " +
82                     "alpha, colorFilter, DefaultFilterQuality)",
83             "androidx.compose.foundation",
84             "androidx.compose.ui.graphics.DefaultAlpha",
85             "androidx.compose.ui.Alignment",
86             "androidx.compose.ui.graphics.drawscope.DrawScope.Companion.DefaultFilterQuality",
87             "androidx.compose.ui.layout.ContentScale.Fit"
88         )
89 )
90 @NonRestartableComposable
91 fun Image(
92     bitmap: ImageBitmap,
93     contentDescription: String?,
94     modifier: Modifier = Modifier,
95     alignment: Alignment = Alignment.Center,
96     contentScale: ContentScale = ContentScale.Fit,
97     alpha: Float = DefaultAlpha,
98     colorFilter: ColorFilter? = null
99 ) {
100     Image(
101         bitmap,
102         contentDescription,
103         modifier,
104         alignment,
105         contentScale,
106         alpha,
107         colorFilter,
108         FilterQuality.Low
109     )
110 }
111 
112 /**
113  * A composable that lays out and draws a given [ImageBitmap]. This will attempt to size the
114  * composable according to the [ImageBitmap]'s given width and height. However, an optional
115  * [Modifier] parameter can be provided to adjust sizing or draw additional content (ex.
116  * background). Any unspecified dimension will leverage the [ImageBitmap]'s size as a minimum
117  * constraint.
118  *
119  * The following sample shows basic usage of an Image composable to position and draw an
120  * [ImageBitmap] on screen
121  *
122  * @sample androidx.compose.foundation.samples.ImageSample
123  *
124  * For use cases that require drawing a rectangular subset of the [ImageBitmap] consumers can use
125  * overload that consumes a [Painter] parameter shown in this sample
126  *
127  * @sample androidx.compose.foundation.samples.BitmapPainterSubsectionSample
128  * @param bitmap The [ImageBitmap] to draw
129  * @param contentDescription text used by accessibility services to describe what this image
130  *   represents. This should always be provided unless this image is used for decorative purposes,
131  *   and does not represent a meaningful action that a user can take. This text should be localized,
132  *   such as by using [androidx.compose.ui.res.stringResource] or similar
133  * @param modifier Modifier used to adjust the layout algorithm or draw decoration content (ex.
134  *   background)
135  * @param alignment Optional alignment parameter used to place the [ImageBitmap] in the given bounds
136  *   defined by the width and height
137  * @param contentScale Optional scale parameter used to determine the aspect ratio scaling to be
138  *   used if the bounds are a different size from the intrinsic size of the [ImageBitmap]
139  * @param alpha Optional opacity to be applied to the [ImageBitmap] when it is rendered onscreen
140  * @param colorFilter Optional ColorFilter to apply for the [ImageBitmap] when it is rendered
141  *   onscreen
142  * @param filterQuality Sampling algorithm applied to the [bitmap] when it is scaled and drawn into
143  *   the destination. The default is [FilterQuality.Low] which scales using a bilinear sampling
144  *   algorithm
145  */
146 @Composable
147 @NonRestartableComposable
Imagenull148 fun Image(
149     bitmap: ImageBitmap,
150     contentDescription: String?,
151     modifier: Modifier = Modifier,
152     alignment: Alignment = Alignment.Center,
153     contentScale: ContentScale = ContentScale.Fit,
154     alpha: Float = DefaultAlpha,
155     colorFilter: ColorFilter? = null,
156     filterQuality: FilterQuality = DefaultFilterQuality
157 ) {
158     val bitmapPainter = remember(bitmap) { BitmapPainter(bitmap, filterQuality = filterQuality) }
159     Image(
160         painter = bitmapPainter,
161         contentDescription = contentDescription,
162         modifier = modifier,
163         alignment = alignment,
164         contentScale = contentScale,
165         alpha = alpha,
166         colorFilter = colorFilter
167     )
168 }
169 
170 /**
171  * A composable that lays out and draws a given [ImageVector]. This will attempt to size the
172  * composable according to the [ImageVector]'s given width and height. However, an optional
173  * [Modifier] parameter can be provided to adjust sizing or draw additional content (ex.
174  * background). Any unspecified dimension will leverage the [ImageVector]'s size as a minimum
175  * constraint.
176  *
177  * @param imageVector The [ImageVector] to draw
178  * @param contentDescription text used by accessibility services to describe what this image
179  *   represents. This should always be provided unless this image is used for decorative purposes,
180  *   and does not represent a meaningful action that a user can take. This text should be localized,
181  *   such as by using [androidx.compose.ui.res.stringResource] or similar
182  * @param modifier Modifier used to adjust the layout algorithm or draw decoration content (ex.
183  *   background)
184  * @param alignment Optional alignment parameter used to place the [ImageVector] in the given bounds
185  *   defined by the width and height
186  * @param contentScale Optional scale parameter used to determine the aspect ratio scaling to be
187  *   used if the bounds are a different size from the intrinsic size of the [ImageVector]
188  * @param alpha Optional opacity to be applied to the [ImageVector] when it is rendered onscreen
189  * @param colorFilter Optional ColorFilter to apply for the [ImageVector] when it is rendered
190  *   onscreen
191  */
192 @Composable
193 @NonRestartableComposable
Imagenull194 fun Image(
195     imageVector: ImageVector,
196     contentDescription: String?,
197     modifier: Modifier = Modifier,
198     alignment: Alignment = Alignment.Center,
199     contentScale: ContentScale = ContentScale.Fit,
200     alpha: Float = DefaultAlpha,
201     colorFilter: ColorFilter? = null
202 ) =
203     Image(
204         painter = rememberVectorPainter(imageVector),
205         contentDescription = contentDescription,
206         modifier = modifier,
207         alignment = alignment,
208         contentScale = contentScale,
209         alpha = alpha,
210         colorFilter = colorFilter
211     )
212 
213 /**
214  * Creates a composable that lays out and draws a given [Painter]. This will attempt to size the
215  * composable according to the [Painter]'s intrinsic size. However, an optional [Modifier] parameter
216  * can be provided to adjust sizing or draw additional content (ex. background)
217  *
218  * **NOTE** a Painter might not have an intrinsic size, so if no LayoutModifier is provided as part
219  * of the Modifier chain this might size the [Image] composable to a width and height of zero and
220  * will not draw any content. This can happen for Painter implementations that always attempt to
221  * fill the bounds like [ColorPainter]
222  *
223  * @sample androidx.compose.foundation.samples.BitmapPainterSample
224  * @param painter to draw
225  * @param contentDescription text used by accessibility services to describe what this image
226  *   represents. This should always be provided unless this image is used for decorative purposes,
227  *   and does not represent a meaningful action that a user can take. This text should be localized,
228  *   such as by using [androidx.compose.ui.res.stringResource] or similar
229  * @param modifier Modifier used to adjust the layout algorithm or draw decoration content (ex.
230  *   background)
231  * @param alignment Optional alignment parameter used to place the [Painter] in the given bounds
232  *   defined by the width and height.
233  * @param contentScale Optional scale parameter used to determine the aspect ratio scaling to be
234  *   used if the bounds are a different size from the intrinsic size of the [Painter]
235  * @param alpha Optional opacity to be applied to the [Painter] when it is rendered onscreen the
236  *   default renders the [Painter] completely opaque
237  * @param colorFilter Optional colorFilter to apply for the [Painter] when it is rendered onscreen
238  */
239 @Composable
240 fun Image(
241     painter: Painter,
242     contentDescription: String?,
243     modifier: Modifier = Modifier,
244     alignment: Alignment = Alignment.Center,
245     contentScale: ContentScale = ContentScale.Fit,
246     alpha: Float = DefaultAlpha,
247     colorFilter: ColorFilter? = null
248 ) {
249     val semantics =
250         if (contentDescription != null) {
251             Modifier.semantics {
252                 this.contentDescription = contentDescription
253                 this.role = Role.Image
254             }
255         } else {
256             Modifier
257         }
258 
259     // Explicitly use a simple Layout implementation here as Spacer squashes any non fixed
260     // constraint with zero
261     Layout(
262         modifier
263             .then(semantics)
264             .clipToBounds()
265             .paint(
266                 painter,
267                 alignment = alignment,
268                 contentScale = contentScale,
269                 alpha = alpha,
270                 colorFilter = colorFilter
271             )
272     ) { _, constraints ->
273         layout(constraints.minWidth, constraints.minHeight) {}
274     }
275 }
276