summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/text/Layout.java36
-rw-r--r--core/tests/coretests/assets/fonts/1em_bidi_font.ttfbin0 -> 2076 bytes
-rw-r--r--core/tests/coretests/src/android/text/LayoutBidiCursorPathTest.java166
3 files changed, 179 insertions, 23 deletions
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 0808cdd6aedb..3ab8a0a8885f 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1806,6 +1806,7 @@ public abstract class Layout {
}
}
+
/**
* Fills in the specified Path with a representation of a cursor
* at the specified offset. This will often be a vertical line
@@ -1821,7 +1822,6 @@ public abstract class Layout {
boolean clamped = shouldClampCursor(line);
float h1 = getPrimaryHorizontal(point, clamped) - 0.5f;
- float h2 = isLevelBoundary(point) ? getSecondaryHorizontal(point, clamped) - 0.5f : h1;
int caps = TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SHIFT_ON) |
TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SELECTING);
@@ -1839,34 +1839,24 @@ public abstract class Layout {
if (h1 < 0.5f)
h1 = 0.5f;
- if (h2 < 0.5f)
- h2 = 0.5f;
- if (Float.compare(h1, h2) == 0) {
- dest.moveTo(h1, top);
- dest.lineTo(h1, bottom);
- } else {
- dest.moveTo(h1, top);
- dest.lineTo(h1, (top + bottom) >> 1);
-
- dest.moveTo(h2, (top + bottom) >> 1);
- dest.lineTo(h2, bottom);
- }
+ dest.moveTo(h1, top);
+ dest.lineTo(h1, bottom);
if (caps == 2) {
- dest.moveTo(h2, bottom);
- dest.lineTo(h2 - dist, bottom + dist);
- dest.lineTo(h2, bottom);
- dest.lineTo(h2 + dist, bottom + dist);
+ dest.moveTo(h1, bottom);
+ dest.lineTo(h1 - dist, bottom + dist);
+ dest.lineTo(h1, bottom);
+ dest.lineTo(h1 + dist, bottom + dist);
} else if (caps == 1) {
- dest.moveTo(h2, bottom);
- dest.lineTo(h2 - dist, bottom + dist);
+ dest.moveTo(h1, bottom);
+ dest.lineTo(h1 - dist, bottom + dist);
- dest.moveTo(h2 - dist, bottom + dist - 0.5f);
- dest.lineTo(h2 + dist, bottom + dist - 0.5f);
+ dest.moveTo(h1 - dist, bottom + dist - 0.5f);
+ dest.lineTo(h1 + dist, bottom + dist - 0.5f);
- dest.moveTo(h2 + dist, bottom + dist);
- dest.lineTo(h2, bottom);
+ dest.moveTo(h1 + dist, bottom + dist);
+ dest.lineTo(h1, bottom);
}
if (fn == 2) {
diff --git a/core/tests/coretests/assets/fonts/1em_bidi_font.ttf b/core/tests/coretests/assets/fonts/1em_bidi_font.ttf
new file mode 100644
index 000000000000..459925433349
--- /dev/null
+++ b/core/tests/coretests/assets/fonts/1em_bidi_font.ttf
Binary files differ
diff --git a/core/tests/coretests/src/android/text/LayoutBidiCursorPathTest.java b/core/tests/coretests/src/android/text/LayoutBidiCursorPathTest.java
new file mode 100644
index 000000000000..1208d7ca194a
--- /dev/null
+++ b/core/tests/coretests/src/android/text/LayoutBidiCursorPathTest.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.text;
+
+import static org.junit.Assert.assertArrayEquals;
+
+import android.content.Context;
+import android.graphics.Path;
+import android.graphics.Typeface;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import android.text.method.MetaKeyKeyListener;
+import android.view.KeyEvent;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Presubmit
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class LayoutBidiCursorPathTest {
+
+ private static final float BIDI_TEXT_SIZE = 12f;
+ private static final String LTR_TEXT = "hello";
+ private static final String RTL_TEXT = "مرحبا";
+
+ private SpannableStringBuilder mBidiText;
+ private TextPaint mTextPaint;
+
+ @Before
+ public void setup() {
+ mBidiText = new SpannableStringBuilder(LTR_TEXT + RTL_TEXT);
+
+ final Context context = InstrumentationRegistry.getTargetContext();
+ mTextPaint = new TextPaint();
+ mTextPaint.setTypeface(
+ Typeface.createFromAsset(context.getAssets(), "fonts/1em_bidi_font.ttf"));
+ mTextPaint.setTextSize(BIDI_TEXT_SIZE);
+ }
+
+ @Test
+ public void testGetCursorPathSegments() {
+ // Setup layout and Act.
+ final Path actualPath = new Path();
+ setupLayoutAndGetCursorPath(actualPath);
+
+ // Expected path.
+ final float h1 = BIDI_TEXT_SIZE * LTR_TEXT.length() - 0.5f;
+ final int top = 0;
+ // sTypoLineGap is set to 1/5 of the Height in font metrics of the font file used here.
+ final int bottom = Math.round(BIDI_TEXT_SIZE + BIDI_TEXT_SIZE / 5f);
+
+ final Path expectedPath = new Path();
+
+ expectedPath.moveTo(h1, top);
+ expectedPath.lineTo(h1, bottom);
+
+ // Assert.
+ assertArrayEquals(expectedPath.approximate(0f), actualPath.approximate(0f), 0f);
+ }
+
+ @Test
+ public void testGetCursorPath_whenShiftIsPressed() {
+ // When shift is pressed a triangle is drawn at the bottom quarter of the cursor.
+ // Set up key.
+ final MetaKeyKeyListener metaKeyKeyListener = new MetaKeyKeyListener() {};
+ metaKeyKeyListener
+ .onKeyDown(null /*view*/, mBidiText, KeyEvent.KEYCODE_SHIFT_RIGHT, null /*keyEvent*/);
+
+ // Setup layout and Act.
+ final Path actualPath = new Path();
+ setupLayoutAndGetCursorPath(actualPath);
+
+ // Expected path.
+ final float h1 = BIDI_TEXT_SIZE * LTR_TEXT.length() - 0.5f;
+ final int top = 0;
+ // sTypoLineGap is set to 1/5 of the Height in font metrics of the font file used here.
+ int bottom = Math.round(BIDI_TEXT_SIZE + BIDI_TEXT_SIZE / 5f);
+ // Draw a triangle at the bottom quarter of the cursor, thus cut the cursor to its 3/4
+ // length.
+ final int dist = (bottom - top) / 4;
+ bottom -= dist;
+
+ final Path expectedPath = new Path();
+
+ expectedPath.moveTo(h1, top);
+ expectedPath.lineTo(h1, bottom);
+
+ expectedPath.moveTo(h1, bottom);
+ expectedPath.lineTo(h1 - dist, bottom + dist);
+
+ expectedPath.moveTo(h1 - dist, bottom + dist - 0.5f);
+ expectedPath.lineTo(h1 + dist, bottom + dist - 0.5f);
+
+ expectedPath.moveTo(h1 + dist, bottom + dist);
+ expectedPath.lineTo(h1, bottom);
+
+ // Assert.
+ assertArrayEquals(expectedPath.approximate(0f), actualPath.approximate(0f), 0f);
+ }
+
+ @Test
+ public void testGetCursorPath_whenAltIsPressed() {
+ // When alt is pressed a triangle is drawn at the top quarter of the cursor.
+ // Set up key.
+ final MetaKeyKeyListener metaKeyKeyListener = new MetaKeyKeyListener() {};
+ metaKeyKeyListener
+ .onKeyDown(null /*view*/, mBidiText, KeyEvent.KEYCODE_ALT_RIGHT, null /*keyEvent*/);
+
+ // Setup layout and Act.
+ final Path actualPath = new Path();
+ setupLayoutAndGetCursorPath(actualPath);
+
+ // Expected path.
+ final float h1 = BIDI_TEXT_SIZE * LTR_TEXT.length() - 0.5f;
+ int top = 0;
+ // sTypoLineGap is set to 1/5 of the Height in font metrics of the font file used here.
+ final int bottom = Math.round(BIDI_TEXT_SIZE + BIDI_TEXT_SIZE / 5f);
+ // Draw a triangle at the top quarter of the cursor, thus cut the cursor to its 3/4 length.
+ final int dist = (bottom - top) / 4;
+ top += dist;
+
+ final Path expectedPath = new Path();
+
+ expectedPath.moveTo(h1, top);
+ expectedPath.lineTo(h1, bottom);
+
+ expectedPath.moveTo(h1, top);
+ expectedPath.lineTo(h1 - dist, top - dist);
+
+ expectedPath.moveTo(h1 - dist, top - dist + 0.5f);
+ expectedPath.lineTo(h1 + dist, top - dist + 0.5f);
+
+ expectedPath.moveTo(h1 + dist, top - dist);
+ expectedPath.lineTo(h1, top);
+
+ // Assert.
+ assertArrayEquals(expectedPath.approximate(0f), actualPath.approximate(0f), 0f);
+ }
+
+ private void setupLayoutAndGetCursorPath(Path path) {
+ final Layout layout = StaticLayout.Builder.obtain(
+ mBidiText, 0, mBidiText.length(), mTextPaint, Integer.MAX_VALUE)
+ .setIncludePad(false)
+ .build();
+
+ layout.getCursorPath(LTR_TEXT.length(), path, mBidiText);
+ }
+}