[go: nahoru, domu]

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(