Use float in text module.
Use float as a width type everywhere in the text module.
Since StaticLayout/BoringLayout only accepts int as width, use
ceil just before passing to them.
Bug: 139947947
Bug: 139894044
Test: ./gradlew test
Test: ./gradlew :ui:ui-text^ConnectedAndroidTest
Change-Id: I725538ee1ce621cbcccfdc3efe3fb375de4bf1e6
diff --git a/ui/ui-android-text/src/main/java/androidx/text/TextLayout.kt b/ui/ui-android-text/src/main/java/androidx/text/TextLayout.kt
index 0f32c9b..45ed74b 100644
--- a/ui/ui-android-text/src/main/java/androidx/text/TextLayout.kt
+++ b/ui/ui-android-text/src/main/java/androidx/text/TextLayout.kt
@@ -53,7 +53,7 @@
import androidx.text.style.BaselineShiftSpan
import java.text.BreakIterator
import java.util.PriorityQueue
-import kotlin.math.max
+import kotlin.math.ceil
/**
* Wrapper for Static Text Layout classes.
@@ -94,8 +94,6 @@
maxIntrinsicWidth = boringMetrics?.width?.toFloat()
?: Layout.getDesiredWidth(charSequence, start, end, textPaint)
- val finalWidth = width.toInt()
- val ellipsizeWidth = finalWidth
val frameworkAlignment = TextAlignmentAdapter.get(alignment)
// BoringLayout won't adjust line height for baselineShift,
@@ -112,19 +110,19 @@
BoringLayoutCompat.Builder(
charSequence,
textPaint,
- finalWidth,
+ ceil(width).toInt(),
boringMetrics
)
.setAlignment(frameworkAlignment)
.setIncludePad(includePadding)
.setEllipsize(ellipsize)
- .setEllipsizedWidth(ellipsizeWidth)
+ .setEllipsizedWidth(ceil(width).toInt())
.build()
} else {
StaticLayoutCompat.Builder(
charSequence,
textPaint,
- finalWidth
+ ceil(width).toInt()
)
.setAlignment(frameworkAlignment)
.setTextDirection(frameworkTextDir)
@@ -132,7 +130,7 @@
.setLineSpacingMultiplier(lineSpacingMultiplier)
.setIncludePad(includePadding)
.setEllipsize(ellipsize)
- .setEllipsizedWidth(ellipsizeWidth)
+ .setEllipsizedWidth(ceil(width).toInt())
.setMaxLines(maxLines)
.setBreakStrategy(breakStrategy)
.setHyphenationFrequency(hyphenationFrequency)
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphTest.kt
index 550c787..a071386 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/platform/AndroidParagraphTest.kt
@@ -1359,6 +1359,14 @@
)
}
+ @Test
+ fun floatingWidth() {
+ val floatWidth = 1.3f
+ val paragraph = simpleParagraph(text = "Hello, World")
+ paragraph.layout(ParagraphConstraints(floatWidth))
+ assertEquals(floatWidth, paragraph.width)
+ }
+
private fun simpleParagraph(
text: String = "",
textStyles: List<AnnotatedString.Item<TextStyle>> = listOf(),
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/TextDelegate.kt b/ui/ui-text/src/main/java/androidx/ui/text/TextDelegate.kt
index 1501142..d02e09c 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/TextDelegate.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/TextDelegate.kt
@@ -17,7 +17,6 @@
package androidx.ui.text
import androidx.annotation.RestrictTo
-import androidx.annotation.RestrictTo.Scope.LIBRARY
import androidx.annotation.VisibleForTesting
import androidx.ui.core.Constraints
import androidx.ui.core.Density
@@ -32,8 +31,6 @@
import androidx.ui.engine.geometry.Offset
import androidx.ui.engine.geometry.Rect
import androidx.ui.engine.geometry.Size
-import androidx.ui.text.style.TextAlign
-import androidx.ui.text.style.TextDirection
import androidx.ui.graphics.Color
import androidx.ui.painting.BlendMode
import androidx.ui.painting.Canvas
@@ -41,9 +38,10 @@
import androidx.ui.painting.Paint
import androidx.ui.painting.Shader
import androidx.ui.text.font.Font
+import androidx.ui.text.style.TextAlign
+import androidx.ui.text.style.TextDirection
import androidx.ui.text.style.TextOverflow
import java.util.Locale
-import kotlin.math.ceil
private val DefaultTextAlign: TextAlign = TextAlign.Start
private val DefaultTextDirection: TextDirection = TextDirection.Ltr
@@ -65,18 +63,6 @@
}
/**
- * Unfortunately, using full precision floating point here causes bad layouts because floating
- * point math isn't associative. If we add and subtract padding, for example, we'll get
- * different values when we estimate sizes and when we actually compute layout because the
- * operations will end up associated differently. To work around this problem for now, we round
- * fractional pixel values up to the nearest whole pixel value. The right long-term fix is to do
- * layout using fixed precision arithmetic.
- */
-internal fun applyFloatingPointHack(layoutValue: Float): Float {
- return ceil(layoutValue)
-}
-
-/**
* An object that paints a [TextSpan] tree into a [Canvas].
*
* To use a [TextDelegate], follow these steps:
@@ -191,7 +177,7 @@
* Valid only after [layout] has been called.
*/
val minIntrinsicWidth: Float
- get() = assumeLayout { applyFloatingPointHack(it.multiParagraph.minIntrinsicWidth) }
+ get() = assumeLayout { it.multiParagraph.minIntrinsicWidth }
/**
* The width at which increasing the width of the text no longer decreases the height.
@@ -199,7 +185,7 @@
* Valid only after [layout] has been called.
*/
val maxIntrinsicWidth: Float
- get() = assumeLayout { applyFloatingPointHack(it.multiParagraph.maxIntrinsicWidth) }
+ get() = assumeLayout { it.multiParagraph.maxIntrinsicWidth }
/**
* The horizontal space required to paint this text.
@@ -207,7 +193,7 @@
* Valid only after [layout] has been called.
*/
val width: Float
- get() = assumeLayout { applyFloatingPointHack(it.size.width) }
+ get() = assumeLayout { it.size.width }
/**
* The vertical space required to paint this text.
@@ -215,7 +201,7 @@
* Valid only after [layout] has been called.
*/
val height: Float
- get() = assumeLayout { applyFloatingPointHack(it.size.height) }
+ get() = assumeLayout { it.size.height }
/**
* Computes the visual position of the glyphs for painting the text.
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt b/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt
index 015f04f..b65fa55 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/platform/AndroidParagraph.kt
@@ -76,7 +76,6 @@
import androidx.ui.text.style.TextDirectionAlgorithm
import androidx.ui.text.style.TextIndent
import java.util.Locale
-import kotlin.math.floor
import kotlin.math.roundToInt
/**
@@ -186,8 +185,6 @@
override fun layout(constraints: ParagraphConstraints) {
val width = constraints.width
- val floorWidth = floor(width)
-
val alignment = toLayoutAlign(paragraphStyle.textAlign)
val textDirectionHeuristic = resolveTextDirectionHeuristics(
@@ -210,7 +207,7 @@
layout = TextLayout(
charSequence = charSequence,
- width = floorWidth,
+ width = width,
textPaint = textPaint,
ellipsize = ellipsize,
alignment = alignment,
@@ -219,7 +216,7 @@
maxLines = maxLines,
justificationMode = justificationMode
)
- this.width = floorWidth
+ this.width = width
}
override fun getOffsetForPosition(position: PxPosition): Int {
diff --git a/ui/ui-text/src/test/java/androidx/ui/text/TextDelegateTest.kt b/ui/ui-text/src/test/java/androidx/ui/text/TextDelegateTest.kt
index 7621404..772eaae 100644
--- a/ui/ui-text/src/test/java/androidx/ui/text/TextDelegateTest.kt
+++ b/ui/ui-text/src/test/java/androidx/ui/text/TextDelegateTest.kt
@@ -105,21 +105,6 @@
assertThat(textDelegate.locale).isEqualTo(locale)
}
- @Test
- fun `applyFloatingPointHack with value is integer toDouble`() {
- assertThat(applyFloatingPointHack(2f)).isEqualTo(2.0f)
- }
-
- @Test
- fun `applyFloatingPointHack with value smaller than half`() {
- assertThat(applyFloatingPointHack(2.2f)).isEqualTo(3.0f)
- }
-
- @Test
- fun `applyFloatingPointHack with value larger than half`() {
- assertThat(applyFloatingPointHack(2.8f)).isEqualTo(3.0f)
- }
-
@Test(expected = AssertionError::class)
fun `minIntrinsicWidth without layout assertion should fail`() {
val textDelegate = TextDelegate(