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