Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b3e9481f authored by Qingqing Deng's avatar Qingqing Deng Committed by Android (Google) Code Review
Browse files

Merge "Disable double cursor for BiDi in Layout."

parents abc7143e 19799c44
Loading
Loading
Loading
Loading
+13 −23
Original line number Diff line number Diff line
@@ -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);
        }

        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) {
+2.03 KiB

File added.

No diff preview for this file type.

+166 −0
Original line number Diff line number Diff line
/*
 * 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);
    }
}