[go: nahoru, domu]

blob: 1b6997409fa7ada885fc0fce91c96262d367f796 [file] [log] [blame]
Nader Jawada736e8f2020-03-03 16:43:37 -08001/*
2 * Copyright 2020 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
Louis Pullen-Freilichddda7be2020-07-17 18:28:12 +010017package androidx.compose.foundation
Nader Jawada736e8f2020-03-03 16:43:37 -080018
19import android.os.Build
Nader Jawada736e8f2020-03-03 16:43:37 -080020import androidx.test.filters.MediumTest
Adam Powell999a89b2020-03-11 09:08:07 -070021import androidx.test.filters.SdkSuppress
Nader Jawada736e8f2020-03-03 16:43:37 -080022import androidx.ui.core.Alignment
23import androidx.ui.core.DensityAmbient
Adam Powell999a89b2020-03-11 09:08:07 -070024import androidx.ui.core.Modifier
Louis Pullen-Freilichddda7be2020-07-17 18:28:12 +010025import androidx.compose.foundation.test.R
Nader Jawada736e8f2020-03-03 16:43:37 -080026import androidx.ui.geometry.Rect
27import androidx.ui.graphics.Canvas
28import androidx.ui.graphics.Color
29import androidx.ui.graphics.ImageAsset
30import androidx.ui.graphics.Paint
31import androidx.ui.graphics.Path
Nader Jawad83158ed2020-04-03 11:11:31 -070032import androidx.ui.core.ContentScale
Nader Jawad038429bf2020-04-14 09:15:15 -070033import androidx.ui.graphics.painter.ImagePainter
Nader Jawad2e1bc332020-04-14 16:28:32 -070034import androidx.ui.core.drawBehind
Filip Pavlis6de64f52020-05-27 18:11:55 +010035import androidx.ui.core.testTag
Nader Jawada736e8f2020-03-03 16:43:37 -080036import androidx.ui.graphics.toArgb
Louis Pullen-Freilich623e4052020-07-19 20:24:03 +010037import androidx.compose.foundation.layout.preferredSize
38import androidx.compose.foundation.layout.preferredSizeIn
39import androidx.compose.foundation.layout.wrapContentSize
Nader Jawad4dd11882020-03-09 18:22:06 -070040import androidx.ui.res.loadVectorResource
Nader Jawada736e8f2020-03-03 16:43:37 -080041import androidx.ui.test.captureToBitmap
Adam Powell999a89b2020-03-11 09:08:07 -070042import androidx.ui.test.createComposeRule
Filip Pavlis659ea722020-07-13 14:14:32 +010043import androidx.ui.test.onNodeWithTag
44import androidx.ui.test.onRoot
Nader Jawad91d33102020-06-11 18:26:11 -070045import androidx.ui.unit.IntOffset
46import androidx.ui.unit.IntSize
Nader Jawada736e8f2020-03-03 16:43:37 -080047import androidx.ui.unit.dp
48import org.junit.Assert
49import org.junit.Rule
50import org.junit.Test
51import org.junit.runner.RunWith
52import org.junit.runners.JUnit4
Nader Jawad2e1bc332020-04-14 16:28:32 -070053import java.util.concurrent.CountDownLatch
54import java.util.concurrent.TimeUnit
Nader Jawada736e8f2020-03-03 16:43:37 -080055
56@MediumTest
57@SdkSuppress(minSdkVersion = Build.VERSION_CODES.O)
58@RunWith(JUnit4::class)
59class ImageTest {
60
61 val contentTag = "ImageTest"
62
63 val imageWidth = 100
64 val imageHeight = 100
65 val containerSize = imageWidth
66
67 val bgColor = Color.Blue
68 val pathColor = Color.Red
69
70 @get:Rule
71 val rule = createComposeRule()
72
73 private fun createImageAsset(): ImageAsset {
74 val image = ImageAsset(imageWidth, imageHeight)
75 val path = Path().apply {
76 lineTo(imageWidth.toFloat(), imageHeight.toFloat())
77 lineTo(0.0f, imageHeight.toFloat())
78 close()
79 }
80 val paint = Paint()
81 Canvas(image).apply {
82 paint.color = bgColor
83 drawRect(
84 Rect.fromLTWH(
85 0.0f,
86 0.0f,
87 imageWidth.toFloat(),
88 imageHeight.toFloat()
89 ),
90 paint
91 )
92
93 paint.color = pathColor
94 drawPath(path, paint)
95 }
96 return image
97 }
98
99 @Test
100 fun testImage() {
101 rule.setContent {
102 val size = (containerSize / DensityAmbient.current.density).dp
Adam Powell999a89b2020-03-11 09:08:07 -0700103 Box(
104 Modifier.preferredSize(size)
Matvei Malkovbf014c12020-07-09 17:40:10 +0100105 .background(color = Color.White)
Adam Powell999a89b2020-03-11 09:08:07 -0700106 .wrapContentSize(Alignment.Center)
107 ) {
Filip Pavlis6de64f52020-05-27 18:11:55 +0100108 Image(modifier = Modifier.testTag(contentTag), asset = createImageAsset())
Nader Jawada736e8f2020-03-03 16:43:37 -0800109 }
110 }
111
112 val bgColorArgb = bgColor.toArgb()
113 val pathArgb = pathColor.toArgb()
114
Filip Pavlis659ea722020-07-13 14:14:32 +0100115 onNodeWithTag(contentTag).captureToBitmap().apply {
Nader Jawada736e8f2020-03-03 16:43:37 -0800116 val imageStartX = width / 2 - imageWidth / 2
117 val imageStartY = height / 2 - imageHeight / 2
118 Assert.assertEquals(bgColorArgb, getPixel(imageStartX + 2, imageStartY))
119 Assert.assertEquals(pathArgb, getPixel(imageStartX, imageStartY + 1))
120 Assert.assertEquals(pathArgb, getPixel(imageStartX + (imageWidth / 2) - 1,
121 imageStartY + (imageHeight / 2) + 1))
122 Assert.assertEquals(bgColorArgb, getPixel(imageStartX + (imageWidth / 2) - 2,
123 imageStartY + (imageHeight / 2) - 5))
124 Assert.assertEquals(pathArgb, getPixel(imageStartX, imageStartY + imageHeight - 1))
125 }
126 }
127
128 @Test
Nader Jawad038429bf2020-04-14 09:15:15 -0700129 fun testImageSubsection() {
130 val subsectionWidth = imageWidth / 2
131 val subsectionHeight = imageHeight / 2
132 rule.setContent {
133 val size = (containerSize / DensityAmbient.current.density).dp
134 Box(
135 Modifier.preferredSize(size)
Matvei Malkovbf014c12020-07-09 17:40:10 +0100136 .background(color = Color.White)
Nader Jawad038429bf2020-04-14 09:15:15 -0700137 .wrapContentSize(Alignment.Center)
138 ) {
Filip Pavlis6de64f52020-05-27 18:11:55 +0100139 Image(
Alexandre Elias96c9ccbd2020-05-19 19:12:54 -0700140 ImagePainter(createImageAsset(),
Nader Jawad91d33102020-06-11 18:26:11 -0700141 IntOffset(
142 imageWidth / 2 - subsectionWidth / 2,
143 imageHeight / 2 - subsectionHeight / 2
Filip Pavlis6de64f52020-05-27 18:11:55 +0100144 ),
Nader Jawad91d33102020-06-11 18:26:11 -0700145 IntSize(subsectionWidth, subsectionHeight)
Nader Jawad038429bf2020-04-14 09:15:15 -0700146 )
Filip Pavlis6de64f52020-05-27 18:11:55 +0100147 )
Nader Jawad038429bf2020-04-14 09:15:15 -0700148 }
149 }
150
151 val boxBgArgb = Color.White.toArgb()
152 val bgColorArgb = bgColor.toArgb()
153 val pathArgb = pathColor.toArgb()
154
Filip Pavlis659ea722020-07-13 14:14:32 +0100155 onRoot().captureToBitmap().apply {
Nader Jawad038429bf2020-04-14 09:15:15 -0700156 val imageStartX = width / 2 - subsectionWidth / 2
157 val imageStartY = height / 2 - subsectionHeight / 2
158 Assert.assertEquals(bgColorArgb, getPixel(imageStartX + 2, imageStartY))
159 Assert.assertEquals(pathArgb, getPixel(imageStartX, imageStartY + 1))
160 Assert.assertEquals(pathArgb, getPixel(imageStartX + (subsectionWidth / 2) - 1,
161 imageStartY + (subsectionHeight / 2) + 1))
162 Assert.assertEquals(bgColorArgb, getPixel(imageStartX + (subsectionWidth / 2) - 2,
163 imageStartY + (subsectionHeight / 2) - 5))
164 Assert.assertEquals(pathArgb, getPixel(imageStartX, imageStartY + subsectionHeight - 1))
165
166 // Verify top left region outside the subsection has a white background
167 Assert.assertEquals(boxBgArgb, getPixel(imageStartX - 1, imageStartY - 1))
168 Assert.assertEquals(boxBgArgb, getPixel(imageStartX - 1, imageStartY))
169 Assert.assertEquals(boxBgArgb, getPixel(imageStartX, imageStartY - 1))
170
171 // Verify top right region outside the subsection has a white background
172 Assert.assertEquals(boxBgArgb,
173 getPixel(imageStartX + subsectionWidth - 1, imageStartY - 1))
174 Assert.assertEquals(boxBgArgb,
175 getPixel(imageStartX + subsectionWidth, imageStartY - 1))
176 Assert.assertEquals(boxBgArgb,
177 getPixel(imageStartX + subsectionWidth, imageStartY))
178
179 // Verify bottom left region outside the subsection has a white background
180 Assert.assertEquals(boxBgArgb,
181 getPixel(imageStartX - 1, imageStartY + subsectionHeight - 1))
182 Assert.assertEquals(boxBgArgb,
183 getPixel(imageStartX - 1, imageStartY + subsectionHeight))
184 Assert.assertEquals(boxBgArgb,
185 getPixel(imageStartX, imageStartY + subsectionHeight))
186
187 // Verify bottom right region outside the subsection has a white background
188 Assert.assertEquals(boxBgArgb,
189 getPixel(imageStartX + subsectionWidth - 1, imageStartY + subsectionHeight))
190 Assert.assertEquals(boxBgArgb,
191 getPixel(imageStartX + subsectionWidth, imageStartY + subsectionHeight))
192 Assert.assertEquals(boxBgArgb,
193 getPixel(imageStartX + subsectionWidth, imageStartY + subsectionHeight - 1))
194 }
195 }
196
197 @Test
Nader Jawada736e8f2020-03-03 16:43:37 -0800198 fun testImageFixedSizeIsStretched() {
199 val imageComposableWidth = imageWidth * 2
200 val imageComposableHeight = imageHeight * 2
201 rule.setContent {
202 val density = DensityAmbient.current.density
203 val size = (containerSize * 2 / density).dp
Adam Powell999a89b2020-03-11 09:08:07 -0700204 Box(
205 Modifier.preferredSize(size)
Matvei Malkovbf014c12020-07-09 17:40:10 +0100206 .background(color = Color.White)
Adam Powell999a89b2020-03-11 09:08:07 -0700207 .wrapContentSize(Alignment.Center)
208 ) {
Filip Pavlis6de64f52020-05-27 18:11:55 +0100209 // The resultant Image composable should be twice the size of the underlying
210 // ImageAsset that is to be drawn and will stretch the content to fit
211 // the bounds
212 Image(asset = createImageAsset(),
213 modifier = Modifier
214 .testTag(contentTag)
215 .preferredSize(
Nader Jawada736e8f2020-03-03 16:43:37 -0800216 (imageComposableWidth / density).dp,
217 (imageComposableHeight / density).dp
Nader Jawad1c3daea2020-06-29 13:32:51 -0700218 )
Filip Pavlis6de64f52020-05-27 18:11:55 +0100219 )
Nader Jawada736e8f2020-03-03 16:43:37 -0800220 }
221 }
222
223 val bgColorArgb = bgColor.toArgb()
224 val pathArgb = pathColor.toArgb()
Filip Pavlis659ea722020-07-13 14:14:32 +0100225 onNodeWithTag(contentTag).captureToBitmap().apply {
Nader Jawada736e8f2020-03-03 16:43:37 -0800226 val imageStartX = width / 2 - imageComposableWidth / 2
227 val imageStartY = height / 2 - imageComposableHeight / 2
228 Assert.assertEquals(bgColorArgb, getPixel(imageStartX + 5, imageStartY))
229 Assert.assertEquals(pathArgb, getPixel(imageStartX, imageStartY + 5))
230 Assert.assertEquals(pathArgb, getPixel(imageStartX + (imageComposableWidth / 2) - 5,
231 imageStartY + (imageComposableHeight / 2) + 5))
232 Assert.assertEquals(bgColorArgb, getPixel(imageStartX + (imageComposableWidth / 2),
233 imageStartY + (imageComposableHeight / 2) - 10))
234 Assert.assertEquals(pathArgb, getPixel(imageStartX, imageStartY +
235 imageComposableHeight - 1))
236 }
237 }
238
239 @Test
240 fun testImageFixedSizeAlignedBottomEnd() {
241 val imageComposableWidth = imageWidth * 2
242 val imageComposableHeight = imageHeight * 2
243 rule.setContent {
244 val density = DensityAmbient.current.density
245 val size = (containerSize * 2 / density).dp
Adam Powell999a89b2020-03-11 09:08:07 -0700246 Box(
247 Modifier.preferredSize(size)
Matvei Malkovbf014c12020-07-09 17:40:10 +0100248 .background(color = Color.White)
Adam Powell999a89b2020-03-11 09:08:07 -0700249 .wrapContentSize(Alignment.Center)
250 ) {
Filip Pavlis6de64f52020-05-27 18:11:55 +0100251 // The resultant Image composable should be twice the size of the underlying
252 // ImageAsset that is to be drawn in the bottom end section of the composable
253 Image(asset = createImageAsset(),
254 modifier = Modifier
255 .testTag(contentTag)
256 .preferredSize(
Nader Jawada736e8f2020-03-03 16:43:37 -0800257 (imageComposableWidth / density).dp,
258 (imageComposableHeight / density).dp
259 ),
Nader Jawad1c3daea2020-06-29 13:32:51 -0700260 // Intentionally do not scale up the contents of the ImageAsset
261 contentScale = ContentScale.Inside,
Filip Pavlis6de64f52020-05-27 18:11:55 +0100262 alignment = Alignment.BottomEnd
263 )
Nader Jawada736e8f2020-03-03 16:43:37 -0800264 }
265 }
266
267 val bgColorArgb = bgColor.toArgb()
268 val pathArgb = pathColor.toArgb()
Filip Pavlis659ea722020-07-13 14:14:32 +0100269 onNodeWithTag(contentTag).captureToBitmap().apply {
Nader Jawada736e8f2020-03-03 16:43:37 -0800270 val composableEndX = width / 2 + imageComposableWidth / 2
271 val composableEndY = height / 2 + imageComposableHeight / 2
272 val imageStartX = composableEndX - imageWidth
273 val imageStartY = composableEndY - imageHeight
274 Assert.assertEquals(bgColorArgb, getPixel(imageStartX + 2, imageStartY))
275 Assert.assertEquals(pathArgb, getPixel(imageStartX, imageStartY + 1))
276 Assert.assertEquals(pathArgb, getPixel(imageStartX + (imageWidth / 2) - 1,
277 imageStartY + (imageHeight / 2) + 1))
278 Assert.assertEquals(bgColorArgb, getPixel(imageStartX + (imageWidth / 2) - 2,
279 imageStartY + (imageHeight / 2) - 5))
280 Assert.assertEquals(pathArgb, getPixel(imageStartX, imageStartY + imageHeight - 1))
281 }
282 }
283
284 @Test
Nader Jawad4dd11882020-03-09 18:22:06 -0700285 fun testVectorScaledCentered() {
286 val boxWidth = 240
287 val boxHeight = 240
Nader Jawad2e1bc332020-04-14 16:28:32 -0700288
289 // latch used to wait until vector resource is loaded asynchronously
290 val vectorLatch = CountDownLatch(1)
Nader Jawada736e8f2020-03-03 16:43:37 -0800291 rule.setContent {
292 val density = DensityAmbient.current.density
Nader Jawad4dd11882020-03-09 18:22:06 -0700293 val size = (boxWidth * 2 / density).dp
294 val minWidth = (boxWidth / density).dp
295 val minHeight = (boxHeight / density).dp
Adam Powell999a89b2020-03-11 09:08:07 -0700296 Box(
297 Modifier.preferredSize(size)
Matvei Malkovbf014c12020-07-09 17:40:10 +0100298 .background(color = Color.White)
Adam Powell999a89b2020-03-11 09:08:07 -0700299 .wrapContentSize(Alignment.Center)
300 ) {
Filip Pavlis6de64f52020-05-27 18:11:55 +0100301 // This is an async call to parse the VectorDrawable xml asset into
302 // a VectorAsset, update the latch once we receive this callback
303 // and draw the Image composable
304 loadVectorResource(R.drawable.ic_vector_asset_test).resource.resource?.let {
305 Image(
306 it,
Alexandre Elias96c9ccbd2020-05-19 19:12:54 -0700307 modifier = Modifier.preferredSizeIn(
308 minWidth = minWidth,
309 minHeight = minHeight
310 )
Nader Jawad1c3daea2020-06-29 13:32:51 -0700311 .drawBehind { vectorLatch.countDown() }
Filip Pavlis6de64f52020-05-27 18:11:55 +0100312 )
Nader Jawada736e8f2020-03-03 16:43:37 -0800313 }
314 }
315 }
316
Nader Jawad2e1bc332020-04-14 16:28:32 -0700317 Assert.assertTrue(vectorLatch.await(5, TimeUnit.SECONDS))
318
Nader Jawada736e8f2020-03-03 16:43:37 -0800319 val imageColor = Color.Red.toArgb()
320 val containerBgColor = Color.White.toArgb()
Filip Pavlis659ea722020-07-13 14:14:32 +0100321 onRoot().captureToBitmap().apply {
Nader Jawad4dd11882020-03-09 18:22:06 -0700322 val imageStartX = width / 2 - boxWidth / 2
323 val imageStartY = height / 2 - boxHeight / 2
Nader Jawada736e8f2020-03-03 16:43:37 -0800324 Assert.assertEquals(containerBgColor, getPixel(imageStartX - 1, imageStartY - 1))
Nader Jawad4dd11882020-03-09 18:22:06 -0700325 Assert.assertEquals(containerBgColor, getPixel(imageStartX + boxWidth + 1,
Nader Jawada736e8f2020-03-03 16:43:37 -0800326 imageStartY - 1))
Nader Jawad4dd11882020-03-09 18:22:06 -0700327 Assert.assertEquals(containerBgColor, getPixel(imageStartX + boxWidth + 1,
328 imageStartY + boxHeight + 1))
Nader Jawada736e8f2020-03-03 16:43:37 -0800329 Assert.assertEquals(containerBgColor, getPixel(imageStartX - 1, imageStartY +
Nader Jawad4dd11882020-03-09 18:22:06 -0700330 boxHeight + 1))
Nader Jawada736e8f2020-03-03 16:43:37 -0800331
Nader Jawad4dd11882020-03-09 18:22:06 -0700332 Assert.assertEquals(imageColor, getPixel(imageStartX, imageStartY + 15))
333 Assert.assertEquals(containerBgColor, getPixel(imageStartX + boxWidth - 2,
334 imageStartY - 1))
335 Assert.assertEquals(imageColor, getPixel(imageStartX + boxWidth - 10,
336 imageStartY + boxHeight - 2))
Nader Jawada736e8f2020-03-03 16:43:37 -0800337 Assert.assertEquals(imageColor, getPixel(imageStartX, imageStartY +
Nader Jawad4dd11882020-03-09 18:22:06 -0700338 boxHeight - 2))
Nader Jawada736e8f2020-03-03 16:43:37 -0800339 }
340 }
341}