182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir/*
282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Copyright (C) 2017 The Android Open Source Project
382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir *
482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Licensed under the Apache License, Version 2.0 (the "License");
582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * you may not use this file except in compliance with the License.
682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * You may obtain a copy of the License at
782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir *
882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir *      http://www.apache.org/licenses/LICENSE-2.0
982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir *
1082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * Unless required by applicable law or agreed to in writing, software
1182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * distributed under the License is distributed on an "AS IS" BASIS,
1282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * See the License for the specific language governing permissions and
1482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir * limitations under the License.
1582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir */
1682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirpackage android.support.text.emoji;
1782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
1882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport static junit.framework.Assert.assertEquals;
1982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
2082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport static org.mockito.Matchers.any;
213dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinirimport static org.mockito.Matchers.eq;
2282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport static org.mockito.Mockito.mock;
233dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinirimport static org.mockito.Mockito.reset;
243dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinirimport static org.mockito.Mockito.times;
253dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinirimport static org.mockito.Mockito.verify;
2682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport static org.mockito.Mockito.when;
2782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
289546df94e6393de504f7ef8dc1b12a1f550c47a8Siyamed Sinirimport android.annotation.TargetApi;
293dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinirimport android.graphics.Canvas;
303dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinirimport android.graphics.Paint;
3182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.graphics.Paint.FontMetricsInt;
329546df94e6393de504f7ef8dc1b12a1f550c47a8Siyamed Sinirimport android.support.test.filters.SdkSuppress;
3382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.support.test.filters.SmallTest;
3482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.support.test.runner.AndroidJUnit4;
3582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport android.text.TextPaint;
3682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
3782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.junit.Before;
3882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.junit.Test;
3982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.junit.runner.RunWith;
4082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.mockito.invocation.InvocationOnMock;
4182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirimport org.mockito.stubbing.Answer;
4282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
4382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir@SmallTest
4482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir@RunWith(AndroidJUnit4.class)
459546df94e6393de504f7ef8dc1b12a1f550c47a8Siyamed Sinir@SdkSuppress(minSdkVersion = 19)
469546df94e6393de504f7ef8dc1b12a1f550c47a8Siyamed Sinir@TargetApi(19)
4782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinirpublic class EmojiSpanTest {
4882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
4982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    @Before
5082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    public void setup() {
5182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        EmojiCompat.reset(TestConfigBuilder.config());
5282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
5382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
5482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    @Test
559546df94e6393de504f7ef8dc1b12a1f550c47a8Siyamed Sinir    public void testGetSize() {
5682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        final short dimensionX = 18;
5782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        final short dimensionY = 20;
5882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        final int fontHeight = 10;
5982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        final float expectedRatio = fontHeight * 1.0f / dimensionY;
6082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        final TextPaint paint = mock(TextPaint.class);
6182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
6282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        // mock TextPaint to return test font metrics
6382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        when(paint.getFontMetricsInt(any(FontMetricsInt.class))).thenAnswer(new Answer<Object>() {
6482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir            @Override
6582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir            public Object answer(InvocationOnMock invocation) throws Throwable {
6682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir                final FontMetricsInt fontMetrics = (FontMetricsInt) invocation.getArguments()[0];
6782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir                fontMetrics.ascent = 0;
6882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir                fontMetrics.descent = -fontHeight;
6982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir                return null;
7082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir            }
7182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        });
7282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
7382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        final EmojiMetadata metadata = mock(EmojiMetadata.class);
7482d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        when(metadata.getWidth()).thenReturn(dimensionX);
7582d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        when(metadata.getHeight()).thenReturn(dimensionY);
7682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        final EmojiSpan span = new TypefaceEmojiSpan(metadata);
7782d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir
7882d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        final int resultSize = span.getSize(paint, "", 0, 0, null);
7982d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        assertEquals((int) (dimensionX * expectedRatio), resultSize);
8082d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        assertEquals(expectedRatio, span.getRatio());
8182d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        assertEquals((int) (dimensionX * expectedRatio), span.getWidth());
8282d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir        assertEquals((int) (dimensionY * expectedRatio), span.getHeight());
8382d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir    }
843dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir
853dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir    @Test
863dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir    public void testBackgroundIndicator() {
873dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        // control the size of the emoji span
883dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        final EmojiMetadata metadata = mock(EmojiMetadata.class);
893dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        when(metadata.getWidth()).thenReturn((short) 10);
903dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        when(metadata.getHeight()).thenReturn((short) 10);
913dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir
923dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        final EmojiSpan span = new TypefaceEmojiSpan(metadata);
933dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        final int spanWidth = span.getSize(mock(Paint.class), "", 0, 0, null);
943dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        // prepare parameters for draw() call
953dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        final Canvas canvas = mock(Canvas.class);
963dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        final float x = 10;
973dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        final int top = 15;
983dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        final int y = 20;
993dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        final int bottom = 30;
1003dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir
1013dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        // verify the case where indicators are disabled
1023dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        EmojiCompat.reset(TestConfigBuilder.config().setEmojiSpanIndicatorEnabled(false));
1033dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        span.draw(canvas, "a", 0 /*start*/, 1 /*end*/, x, top, y, bottom, mock(Paint.class));
1043dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir
1053dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        verify(canvas, times(0)).drawRect(eq(x), eq((float) top), eq(x + spanWidth),
1063dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir                eq((float) bottom), any(Paint.class));
1073dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir
1083dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        // verify the case where indicators are enabled
1093dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        EmojiCompat.reset(TestConfigBuilder.config().setEmojiSpanIndicatorEnabled(true));
1103dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        reset(canvas);
1113dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        span.draw(canvas, "a", 0 /*start*/, 1 /*end*/, x, top, y, bottom, mock(Paint.class));
1123dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir
1133dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir        verify(canvas, times(1)).drawRect(eq(x), eq((float) top), eq(x + spanWidth),
1143dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir                eq((float) bottom), any(Paint.class));
1153dc8b512ac3a1a8fb0b7b2618246d50fd2f3367bSiyamed Sinir    }
11682d2cc1cf0c2bfdd5121e6d6913dfe9fcaacf439Siyamed Sinir}
117