Add getLineTop to Paragraph and MultiParagraph

Bug: N/A
Test: ./gradlew test
Test: ./gradlew ui:ui-text:cAT
Change-Id: I9d311c98b235cba328643c2d00affa66f941801f
diff --git a/ui/ui-text/api/0.1.0-dev05.txt b/ui/ui-text/api/0.1.0-dev05.txt
index d946288..a133a55 100644
--- a/ui/ui-text/api/0.1.0-dev05.txt
+++ b/ui/ui-text/api/0.1.0-dev05.txt
@@ -300,6 +300,7 @@
     method public float getLineHeight(int lineIndex);
     method public float getLineLeft(int lineIndex);
     method public float getLineRight(int lineIndex);
+    method public float getLineTop(int lineIndex);
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public int getMaxLines();
@@ -347,6 +348,7 @@
     method public float getLineHeight(int lineIndex);
     method public float getLineLeft(int lineIndex);
     method public float getLineRight(int lineIndex);
+    method public float getLineTop(int lineIndex);
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public float getMinIntrinsicWidth();
diff --git a/ui/ui-text/api/current.txt b/ui/ui-text/api/current.txt
index d946288..a133a55 100644
--- a/ui/ui-text/api/current.txt
+++ b/ui/ui-text/api/current.txt
@@ -300,6 +300,7 @@
     method public float getLineHeight(int lineIndex);
     method public float getLineLeft(int lineIndex);
     method public float getLineRight(int lineIndex);
+    method public float getLineTop(int lineIndex);
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public int getMaxLines();
@@ -347,6 +348,7 @@
     method public float getLineHeight(int lineIndex);
     method public float getLineLeft(int lineIndex);
     method public float getLineRight(int lineIndex);
+    method public float getLineTop(int lineIndex);
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public float getMinIntrinsicWidth();
diff --git a/ui/ui-text/api/public_plus_experimental_0.1.0-dev05.txt b/ui/ui-text/api/public_plus_experimental_0.1.0-dev05.txt
index d946288..a133a55 100644
--- a/ui/ui-text/api/public_plus_experimental_0.1.0-dev05.txt
+++ b/ui/ui-text/api/public_plus_experimental_0.1.0-dev05.txt
@@ -300,6 +300,7 @@
     method public float getLineHeight(int lineIndex);
     method public float getLineLeft(int lineIndex);
     method public float getLineRight(int lineIndex);
+    method public float getLineTop(int lineIndex);
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public int getMaxLines();
@@ -347,6 +348,7 @@
     method public float getLineHeight(int lineIndex);
     method public float getLineLeft(int lineIndex);
     method public float getLineRight(int lineIndex);
+    method public float getLineTop(int lineIndex);
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public float getMinIntrinsicWidth();
diff --git a/ui/ui-text/api/public_plus_experimental_current.txt b/ui/ui-text/api/public_plus_experimental_current.txt
index d946288..a133a55 100644
--- a/ui/ui-text/api/public_plus_experimental_current.txt
+++ b/ui/ui-text/api/public_plus_experimental_current.txt
@@ -300,6 +300,7 @@
     method public float getLineHeight(int lineIndex);
     method public float getLineLeft(int lineIndex);
     method public float getLineRight(int lineIndex);
+    method public float getLineTop(int lineIndex);
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public int getMaxLines();
@@ -347,6 +348,7 @@
     method public float getLineHeight(int lineIndex);
     method public float getLineLeft(int lineIndex);
     method public float getLineRight(int lineIndex);
+    method public float getLineTop(int lineIndex);
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public float getMinIntrinsicWidth();
diff --git a/ui/ui-text/api/restricted_0.1.0-dev05.txt b/ui/ui-text/api/restricted_0.1.0-dev05.txt
index d946288..a133a55 100644
--- a/ui/ui-text/api/restricted_0.1.0-dev05.txt
+++ b/ui/ui-text/api/restricted_0.1.0-dev05.txt
@@ -300,6 +300,7 @@
     method public float getLineHeight(int lineIndex);
     method public float getLineLeft(int lineIndex);
     method public float getLineRight(int lineIndex);
+    method public float getLineTop(int lineIndex);
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public int getMaxLines();
@@ -347,6 +348,7 @@
     method public float getLineHeight(int lineIndex);
     method public float getLineLeft(int lineIndex);
     method public float getLineRight(int lineIndex);
+    method public float getLineTop(int lineIndex);
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public float getMinIntrinsicWidth();
diff --git a/ui/ui-text/api/restricted_current.txt b/ui/ui-text/api/restricted_current.txt
index d946288..a133a55 100644
--- a/ui/ui-text/api/restricted_current.txt
+++ b/ui/ui-text/api/restricted_current.txt
@@ -300,6 +300,7 @@
     method public float getLineHeight(int lineIndex);
     method public float getLineLeft(int lineIndex);
     method public float getLineRight(int lineIndex);
+    method public float getLineTop(int lineIndex);
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public int getMaxLines();
@@ -347,6 +348,7 @@
     method public float getLineHeight(int lineIndex);
     method public float getLineLeft(int lineIndex);
     method public float getLineRight(int lineIndex);
+    method public float getLineTop(int lineIndex);
     method public float getLineWidth(int lineIndex);
     method public float getMaxIntrinsicWidth();
     method public float getMinIntrinsicWidth();
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/MultiParagraphIntegrationTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/MultiParagraphIntegrationTest.kt
index a21ee43..c587f71 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/MultiParagraphIntegrationTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/MultiParagraphIntegrationTest.kt
@@ -670,6 +670,43 @@
     }
 
     @Test
+    fun getLineTop() {
+        with(defaultDensity) {
+            val text = createAnnotatedString("a", "a", "a")
+
+            val fontSize = 50.sp
+            val fontSizeInPx = fontSize.toPx().value
+
+            val paragraph = simpleMultiParagraph(
+                text = text,
+                fontSize = fontSize
+            )
+
+            for (i in 0 until paragraph.lineCount) {
+                assertWithMessage("bottom of line $i doesn't match")
+                    .that(paragraph.getLineTop(i))
+                    .isEqualTo(fontSizeInPx * i)
+            }
+        }
+    }
+
+    @Test(expected = java.lang.IllegalArgumentException::class)
+    fun getLineTop_negative_throw_exception() {
+        val text = "abc"
+        val paragraph = simpleMultiParagraph(text = text)
+
+        paragraph.getLineTop(-1)
+    }
+
+    @Test(expected = java.lang.IllegalArgumentException::class)
+    fun getLineTop_greaterThanOrEqual_lineCount_throw_exception() {
+        val text = "abc"
+        val paragraph = simpleMultiParagraph(text = text)
+
+        paragraph.getLineTop(paragraph.lineCount)
+    }
+
+    @Test
     fun getLineBottom() {
         with(defaultDensity) {
             val text = createAnnotatedString("a", "a", "a")
diff --git a/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt b/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt
index 3b8e744..21384d1 100644
--- a/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt
+++ b/ui/ui-text/src/androidTest/java/androidx/ui/text/ParagraphIntegrationTest.kt
@@ -2179,6 +2179,23 @@
     }
 
     @Test
+    fun getLineTop() {
+        with(defaultDensity) {
+            val text = "aaa\nbbb"
+
+            val fontSize = 50.sp
+            val fontSizeInPx = fontSize.toPx().value
+
+            val paragraph = simpleParagraph(
+                text = text,
+                style = TextStyle(fontSize = fontSize)
+            )
+            assertThat(paragraph.getLineTop(0)).isZero()
+            assertThat(paragraph.getLineTop(1)).isEqualTo(fontSizeInPx)
+        }
+    }
+
+    @Test
     fun getLineBottom() {
         with(defaultDensity) {
             val text = "aaa\nbbb"
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/MultiParagraph.kt b/ui/ui-text/src/main/java/androidx/ui/text/MultiParagraph.kt
index 7942084..5f8c358a 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/MultiParagraph.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/MultiParagraph.kt
@@ -422,6 +422,17 @@
         }
     }
 
+    /** Returns the top y coordinate of the given line. */
+    fun getLineTop(lineIndex: Int): Float {
+        requireLineIndexInRange(lineIndex)
+
+        val paragraphIndex = findParagraphByLineIndex(paragraphInfoList, lineIndex)
+
+        return with(paragraphInfoList[paragraphIndex]) {
+            paragraph.getLineTop(lineIndex.toLocalLineIndex()).toGlobalYPosition()
+        }
+    }
+
     /** Returns the bottom y coordinate of the given line. */
     fun getLineBottom(lineIndex: Int): Float {
         requireLineIndexInRange(lineIndex)
diff --git a/ui/ui-text/src/main/java/androidx/ui/text/Paragraph.kt b/ui/ui-text/src/main/java/androidx/ui/text/Paragraph.kt
index e2c17d0..b44323e 100644
--- a/ui/ui-text/src/main/java/androidx/ui/text/Paragraph.kt
+++ b/ui/ui-text/src/main/java/androidx/ui/text/Paragraph.kt
@@ -106,9 +106,10 @@
     /** Returns the right x Coordinate of the given line. */
     fun getLineRight(lineIndex: Int): Float
 
-    /**
-     * Returns the bottom y coordinate of the given line.
-     */
+    /** Returns the bottom y coordinate of the given line. */
+    fun getLineTop(lineIndex: Int): Float
+
+    /** Returns the bottom y coordinate of the given line. */
     fun getLineBottom(lineIndex: Int): Float
 
     /** Returns the height of the given line. */
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 36708af..15bc2a8 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
@@ -219,6 +219,8 @@
 
     override fun getLineRight(lineIndex: Int): Float = layout.getLineRight(lineIndex)
 
+    override fun getLineTop(lineIndex: Int): Float = layout.getLineTop(lineIndex)
+
     override fun getLineBottom(lineIndex: Int): Float = layout.getLineBottom(lineIndex)
 
     override fun getLineHeight(lineIndex: Int): Float = layout.getLineHeight(lineIndex)