Skip to content

Commit c777c73

Browse files
ssancho14Gerrit Code Review
authored and
Gerrit Code Review
committed
Merge "Fixed bug on smoothing." into androidx-main
2 parents 0925b4d + 5dd7512 commit c777c73

File tree

3 files changed

+109
-7
lines changed

3 files changed

+109
-7
lines changed

graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/RoundedPolygonTest.kt

+104-1
Original file line numberDiff line numberDiff line change
@@ -109,4 +109,107 @@ class RoundedPolygonTest {
109109
assertEqualish(0.5f, lowerEdge.p3.x)
110110
assertEqualish(0.0f, lowerEdge.p3.y)
111111
}
112-
}
112+
113+
/*
114+
* In the following tests, we check how much was cut for the top left (vertex 0) and bottom
115+
* left corner (vertex 3).
116+
* In particular, both vertex are competing for space in the left side.
117+
*
118+
* Vertex 0 Vertex 1
119+
* *---------------------*
120+
* | |
121+
* *---------------------*
122+
* Vertex 3 Vertex 2
123+
*/
124+
private val points = 20
125+
126+
@Test
127+
fun unevenSmoothingTest() {
128+
// Vertex 3 has the default 0.5 radius, 0 smoothing.
129+
// Vertex 0 has 0.4 radius, and smoothing varying from 0 to 1.
130+
repeat(points + 1) {
131+
val smooth = it.toFloat() / points
132+
doUnevenSmoothTest(
133+
CornerRounding(0.4f, smooth),
134+
expectedV0SX = 0.4f * (1 + smooth),
135+
expectedV0SY = (0.4f * (1 + smooth)).coerceAtMost(0.5f),
136+
expectedV3SY = 0.5f,
137+
)
138+
}
139+
}
140+
141+
@Test
142+
fun unevenSmoothingTest2() {
143+
// Vertex 3 has 0.2f radius and 0.2f smoothing, so it takes at most 0.4f
144+
// Vertex 0 has 0.4f radius and smoothing varies from 0 to 1, when it reaches 0.5 it starts
145+
// competing with vertex 3 for space.
146+
repeat(points + 1) {
147+
val smooth = it.toFloat() / points
148+
149+
val smoothWantedV0 = 0.4f * smooth
150+
val smoothWantedV3 = 0.2f
151+
152+
// There is 0.4f room for smoothing
153+
val factor = (0.4f / (smoothWantedV0 + smoothWantedV3)).coerceAtMost(1f)
154+
doUnevenSmoothTest(
155+
CornerRounding(0.4f, smooth),
156+
expectedV0SX = 0.4f * (1 + smooth),
157+
expectedV0SY = 0.4f + factor * smoothWantedV0,
158+
expectedV3SY = 0.2f + factor * smoothWantedV3,
159+
rounding3 = CornerRounding(0.2f, 1f)
160+
)
161+
}
162+
}
163+
164+
@Test
165+
fun unevenSmoothingTest3() {
166+
// Vertex 3 has 0.6f radius.
167+
// Vertex 0 has 0.4f radius and smoothing varies from 0 to 1. There is no room for smoothing
168+
// on the segment between these vertices, but vertex 0 can still have smoothing on the top
169+
// side.
170+
repeat(points + 1) {
171+
val smooth = it.toFloat() / points
172+
173+
doUnevenSmoothTest(
174+
CornerRounding(0.4f, smooth),
175+
expectedV0SX = 0.4f * (1 + smooth),
176+
expectedV0SY = 0.4f,
177+
expectedV3SY = 0.6f,
178+
rounding3 = CornerRounding(0.6f)
179+
)
180+
}
181+
}
182+
183+
private fun doUnevenSmoothTest(
184+
// Corner rounding parameter for vertex 0 (top left)
185+
rounding0: CornerRounding,
186+
expectedV0SX: Float, // Expected total cut from vertex 0 towards vertex 1
187+
expectedV0SY: Float, // Expected total cut from vertex 0 towards vertex 3
188+
expectedV3SY: Float, // Expected total cut from vertex 3 towards vertex 0
189+
// Corner rounding parameter for vertex 3 (bottom left)
190+
rounding3: CornerRounding = CornerRounding(0.5f)
191+
) {
192+
val p0 = PointF(0f, 0f)
193+
val p1 = PointF(5f, 0f)
194+
val p2 = PointF(5f, 1f)
195+
val p3 = PointF(0f, 1f)
196+
197+
val pvRounding = listOf(
198+
rounding0,
199+
CornerRounding.Unrounded,
200+
CornerRounding.Unrounded,
201+
rounding3,
202+
)
203+
val polygon = RoundedPolygon(
204+
vertices = listOf(p0, p1, p2, p3),
205+
perVertexRounding = pvRounding
206+
)
207+
val (e01, _, _, e30) = polygon.features.filterIsInstance<RoundedPolygon.Edge>()
208+
val msg = "r0 = ${show(rounding0)}, r3 = ${show(rounding3)}"
209+
assertEqualish(expectedV0SX, e01.cubics.first().p0.x, msg)
210+
assertEqualish(expectedV0SY, e30.cubics.first().p3.y, msg)
211+
assertEqualish(expectedV3SY, 1f - e30.cubics.first().p0.y, msg)
212+
}
213+
214+
private fun show(cr: CornerRounding) = "(r=${cr.radius}, s=${cr.smoothing})"
215+
}

graphics/graphics-shapes/src/androidTest/java/androidx/graphics/shapes/TestUtils.kt

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ fun assertPointLessish(expected: PointF, actual: PointF) {
4545
assertTrue(actual.y <= expected.y + Epsilon)
4646
}
4747

48-
fun assertEqualish(expected: Float, actual: Float) {
49-
assertEquals(expected, actual, Epsilon)
48+
fun assertEqualish(expected: Float, actual: Float, message: String? = null) {
49+
assertEquals(message ?: "", expected, actual, Epsilon)
5050
}
5151

5252
fun assertInBounds(shape: CubicShape, minPoint: PointF, maxPoint: PointF) {

graphics/graphics-shapes/src/main/java/androidx/graphics/shapes/RoundedPolygon.kt

+3-4
Original file line numberDiff line numberDiff line change
@@ -228,21 +228,20 @@ class RoundedPolygon {
228228
sideSize / expectedRoundCut to 0f
229229
} else if (expectedCut > sideSize) {
230230
// We can do full rounding, but not full smoothing.
231-
1f to (sideSize - expectedRoundCut) / expectedCut
231+
1f to (sideSize - expectedRoundCut) / (expectedCut - expectedRoundCut)
232232
} else {
233233
// There is enough room for rounding & smoothing.
234-
0f to 1f
234+
1f to 1f
235235
}
236236
}
237-
238237
// Create and store list of beziers for each [potentially] rounded corner
239238
for (i in 0 until n) {
240239
// allowedCuts[0] is for the side from the previous corner to this one,
241240
// allowedCuts[1] is for the side from this corner to the next one.
242241
val allowedCuts = (0..1).map { delta ->
243242
val (roundCutRatio, cutRatio) = cutAdjusts[(i + n - 1 + delta) % n]
244243
roundedCorners[i].expectedRoundCut * roundCutRatio +
245-
roundedCorners[i].expectedCut * cutRatio
244+
(roundedCorners[i].expectedCut - roundedCorners[i].expectedRoundCut) * cutRatio
246245
}
247246
corners.add(
248247
roundedCorners[i].getCubics(

0 commit comments

Comments
 (0)